package org.jeecg.modules.demo.app.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.saobei.open.sdk.model.response.trade.SaobeiMiniPayResponse;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.demo.allvipcard.entity.AllVipcard;
import org.jeecg.modules.demo.allvipcard.mapper.AllVipcardMapper;
import org.jeecg.modules.demo.allvipcard.service.IAllVipcardService;
import org.jeecg.modules.demo.allvipcardstyle.entity.AllVipcardStyle;
import org.jeecg.modules.demo.allvipcardstyle.service.IAllVipcardStyleService;
import org.jeecg.modules.demo.app.service.AppService;
import org.jeecg.modules.demo.basemembersharecoupon.entity.BaseMemberShareCoupon;
import org.jeecg.modules.demo.basemembersharecoupon.service.IBaseMemberShareCouponService;
import org.jeecg.modules.demo.basemembersharevip.entity.BaseMemberShareVip;
import org.jeecg.modules.demo.basemembersharevip.service.IBaseMemberShareVipService;
import org.jeecg.modules.demo.basemembertoreceivevip.entity.BaseMemberToReceiveVip;
import org.jeecg.modules.demo.basemembertoreceivevip.service.IBaseMemberToReceiveVipService;
import org.jeecg.modules.demo.basemembertoreceivevipcoupon.entity.BaseMemberToReceiveVipCoupon;
import org.jeecg.modules.demo.basemembertoreceivevipcoupon.service.IBaseMemberToReceiveVipCouponService;
import org.jeecg.modules.demo.basemembervip.entity.BaseMemberVip;
import org.jeecg.modules.demo.basemembervip.service.IBaseMemberVipService;
import org.jeecg.modules.demo.basemembervipcoupon.entity.BaseMemberVipCoupon;
import org.jeecg.modules.demo.basemembervipcoupon.service.IBaseMemberVipCouponService;
import org.jeecg.modules.demo.baseorde.entity.BaseOrder;
import org.jeecg.modules.demo.baseorde.service.IBaseOrderService;
import org.jeecg.modules.demo.baseordercommodity.entity.BaseOrderCommodity;
import org.jeecg.modules.demo.baseordercommodity.service.IBaseOrderCommodityService;
import org.jeecg.modules.demo.baseordercommoditywriteoff.entity.BaseOrderCommodityWriteoff;
import org.jeecg.modules.demo.baseordercommoditywriteoff.service.IBaseOrderCommodityWriteoffService;
import org.jeecg.modules.demo.baseorderproject.entity.BaseOrderProject;
import org.jeecg.modules.demo.baseorderproject.service.IBaseOrderProjectService;
import org.jeecg.modules.demo.baseorderservicewriteoff.entity.BaseOrderServiceWriteoff;
import org.jeecg.modules.demo.baseorderservicewriteoff.service.IBaseOrderServiceWriteoffService;
import org.jeecg.modules.demo.baseorderwriteoffrecord.entity.BaseOrderWriteoffRecord;
import org.jeecg.modules.demo.baseorderwriteoffrecord.service.IBaseOrderWriteoffRecordService;
import org.jeecg.modules.demo.basepayorder.entity.BasePayOrder;
import org.jeecg.modules.demo.basepayorder.service.IBasePayOrderService;
import org.jeecg.modules.demo.basepreorder.service.IBasePreOrderService;
import org.jeecg.modules.demo.baseselforder.entity.BaseSelfOrder;
import org.jeecg.modules.demo.baseselforder.service.IBaseSelfOrderService;
import org.jeecg.modules.demo.baseselfordercommodity.entity.BaseSelfOrderCommodity;
import org.jeecg.modules.demo.baseselfordercommodity.service.IBaseSelfOrderCommodityService;
import org.jeecg.modules.demo.basestaffstatus.entity.BaseStaffStatus;
import org.jeecg.modules.demo.basestaffstatus.service.IBaseStaffStatusService;
import org.jeecg.modules.demo.basestaffstatusspecial.entity.BaseStaffStatusSpecial;
import org.jeecg.modules.demo.basestaffstatusspecial.service.IBaseStaffStatusSpecialService;
import org.jeecg.modules.demo.blancechangerecord.entity.BalanceChangeRecord;
import org.jeecg.modules.demo.blancechangerecord.mapper.BalanceChangeRecordMapper;
import org.jeecg.modules.demo.cashier.service.CashierService;
import org.jeecg.modules.demo.commoditygroup.entity.CommodityGroup;
import org.jeecg.modules.demo.commoditygroup.service.ICommodityGroupService;
import org.jeecg.modules.demo.commoditymanagement.entity.CommodityManagement;
import org.jeecg.modules.demo.commoditymanagement.service.ICommodityManagementService;
import org.jeecg.modules.demo.couponmanagement.entity.CouponManagement;
import org.jeecg.modules.demo.instoragedetail.entity.InStorageDetail;
import org.jeecg.modules.demo.issuingrecords.entity.IssuingRecords;
import org.jeecg.modules.demo.issuingrecords.service.IIssuingRecordsService;
import org.jeecg.modules.demo.levelset.entity.LevelSet;
import org.jeecg.modules.demo.levelset.service.ILevelSetService;
import org.jeecg.modules.demo.membermanagement.entity.MemberManagement;
import org.jeecg.modules.demo.membermanagement.service.IMemberManagementService;
import org.jeecg.modules.demo.msgtemplatelist.entity.MsgTemplate;
import org.jeecg.modules.demo.msgtemplatelist.service.IMsgTemplateService;
import org.jeecg.modules.demo.officialaccounttoken.entity.OfficialAccountToken;
import org.jeecg.modules.demo.officialaccounttoken.service.IOfficialAccountTokenService;
import org.jeecg.modules.demo.officialaccountuser.entity.OfficialAccountUser;
import org.jeecg.modules.demo.officialaccountuser.service.IOfficialAccountUserService;
import org.jeecg.modules.demo.outstoragedetail.entity.OutStorageDetail;
import org.jeecg.modules.demo.outstoragedetail.service.IOutStorageDetailService;
import org.jeecg.modules.demo.outstoragemain.entity.OutStorageMain;
import org.jeecg.modules.demo.outstoragemain.service.IOutStorageMainService;
import org.jeecg.modules.demo.projectgroup.entity.ProjectGroup;
import org.jeecg.modules.demo.projectgroup.service.IProjectGroupService;
import org.jeecg.modules.demo.projectmanagement.entity.ProjectManagement;
import org.jeecg.modules.demo.projectmanagement.service.IProjectManagementService;
import org.jeecg.modules.demo.rechargerecord.entity.RechargeRecord;
import org.jeecg.modules.demo.rechargerecord.service.IRechargeRecordService;
import org.jeecg.modules.demo.reserverecord.entity.ReserveRecord;
import org.jeecg.modules.demo.reserverecord.service.IReserveRecordService;
import org.jeecg.modules.demo.saobeiorderrecord.entity.SaobeiOrderRecord;
import org.jeecg.modules.demo.saobeiorderrecord.service.ISaobeiOrderRecordService;
import org.jeecg.modules.demo.shopcommoditycart.entity.ShopCommodityCart;
import org.jeecg.modules.demo.shopcommoditycart.service.IShopCommodityCartService;
import org.jeecg.modules.demo.shopprojectcart.entity.ShopProjectCart;
import org.jeecg.modules.demo.shopprojectcart.service.IShopProjectCartService;
import org.jeecg.modules.demo.staffmanagement.entity.StaffManagement;
import org.jeecg.modules.demo.staffmanagement.service.IStaffManagementService;
import org.jeecg.modules.demo.stockgroup.entity.StockGroup;
import org.jeecg.modules.demo.stockgroup.service.IStockGroupService;
import org.jeecg.modules.demo.stockmanage.controller.StockManageController;
import org.jeecg.modules.demo.stockmanage.entity.StockDividendCount;
import org.jeecg.modules.demo.stockmanage.entity.StockManage;
import org.jeecg.modules.demo.stockmanage.service.IStockManageService;
import org.jeecg.modules.demo.storageoutindetail.entity.StorageOutinDetail;
import org.jeecg.modules.demo.storageoutindetail.service.IStorageOutinDetailService;
import org.jeecg.modules.demo.storeemplee.entity.StoreEmplee;
import org.jeecg.modules.demo.storeemplee.service.IStoreEmpleeService;
import org.jeecg.modules.demo.storeinfo.entity.StoreInfo;
import org.jeecg.modules.demo.storeinfo.service.IStoreInfoService;
import org.jeecg.modules.demo.storeproject.entity.StoreProject;
import org.jeecg.modules.demo.storeproject.service.IStoreProjectService;
import org.jeecg.modules.demo.storeprojectgroup.entity.StoreProjectGroup;
import org.jeecg.modules.demo.storeprojectgroup.service.IStoreProjectGroupService;
import org.jeecg.modules.demo.vipcardcoupon.entity.VipCardCoupon;
import org.jeecg.modules.demo.vipcardcoupon.service.IVipCardCouponService;
import org.jeecg.modules.demo.vipcarddrawrecord.entity.VipcardDrawRecord;
import org.jeecg.modules.demo.vipcarddrawrecord.service.IVipcardDrawRecordService;
import org.jeecg.modules.demo.vipcardvedio.entity.VipCardVedio;
import org.jeecg.modules.demo.vipcardvedio.service.IVipCardVedioService;
import org.jeecg.modules.demo.vipcardvediocomment.entity.VipCardVedioComment;
import org.jeecg.modules.demo.vipcardvediocomment.service.IVipCardVedioCommentService;
import org.jeecg.modules.demo.viporderrecord.entity.VipOrderRecord;
import org.jeecg.modules.demo.viporderrecord.service.IVipOrderRecordService;
import org.jeecg.modules.demo.widthmanagement.entity.WidthManagement;
import org.jeecg.modules.demo.widthmanagement.service.IWidthManagementService;
import org.jeecg.modules.saobei.Saobei;
import org.jeecg.modules.util.*;
import org.jeecg.modules.weixin.util;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;



@RestController
@RequestMapping("/app")
@Slf4j
public class AppController {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private CashierService cashierService;
    @Autowired
    private AppService appService;
    @Autowired
    private IMemberManagementService memberManagementService;
    @Autowired
    private IAllVipcardStyleService allVipcardStyleService;

    @Autowired
    private IStockManageService stockManageService;
    @Autowired
    private IStaffManagementService staffManagementService;
    @Autowired
    private ICommodityGroupService commodityGroupService;
    @Autowired
    private ICommodityManagementService commodityManagementService;
    @Autowired
    private IProjectGroupService projectGroupService;
    @Autowired
    private IProjectManagementService projectManagementService;
    @Autowired
    private IBaseOrderService baseOrderService;
    @Autowired
    private IBaseOrderCommodityService baseOrderCommodityService;
    @Autowired
    private IBaseSelfOrderService baseSelfOrderService;
    @Autowired
    private IBaseSelfOrderCommodityService baseSelfOrderCommodityService;
    @Autowired
    private IBaseOrderProjectService baseOrderProjectService;
    @Autowired
    private IBaseOrderServiceWriteoffService baseOrderServiceWriteoffService;
    @Autowired
    private IBaseOrderCommodityWriteoffService baseOrderCommodityWriteoffService;
    @Autowired
    private IBasePreOrderService basePreOrderService;
    @Autowired
    private IStoreInfoService storeInfoService;
    @Autowired
    private ILevelSetService levelSetService;
    @Autowired
    private IBaseMemberVipService baseMemberVipService;
    @Autowired
    private IBaseMemberVipCouponService baseMemberVipCouponService;
    @Autowired
    private IBaseMemberShareVipService baseMemberShareVipService;
    @Autowired
    private IBaseMemberShareCouponService baseMemberShareCouponService;
    @Autowired
    private IBaseOrderWriteoffRecordService baseOrderWriteoffRecordService;
    @Autowired
    private IBasePayOrderService basePayOrderService;
    @Autowired
    private IIssuingRecordsService issuingRecordsService;
    @Autowired
    private IBaseStaffStatusService baseStaffStatusService;
    @Autowired
    private IBaseStaffStatusSpecialService baseStaffStatusSpecialService;
    @Autowired
    private IOutStorageMainService outStorageMainService;
    @Autowired
    private IOutStorageDetailService outStorageDetailService;
    @Autowired
    private IStorageOutinDetailService storageOutinDetailService;
    @Autowired
    private IAllVipcardService allVipcardService;
    @Autowired
    private IVipCardCouponService vipCardCouponService;
    @Autowired
    private IWidthManagementService widthManagementService;
    @Autowired
    private IOfficialAccountUserService officialAccountUserService;
    @Autowired
    private IOfficialAccountTokenService officialAccountTokenService;
    @Autowired
    private IShopCommodityCartService shopCommodityCartService;
    @Autowired
    private IShopProjectCartService shopProjectCartService;
    @Autowired
    private IBaseMemberToReceiveVipService baseMemberToReceiveVipService;
    @Autowired
    private IBaseMemberToReceiveVipCouponService baseMemberToReceiveVipCouponService;
    @Autowired
    private IVipOrderRecordService vipOrderRecordService;
    @Autowired
    private ISaobeiOrderRecordService saobeiOrderRecordService;
    @Autowired
    private IRechargeRecordService rechargeRecordService;
    @Autowired
    private IMsgTemplateService msgTemplateListService;
    @Autowired
    private IVipCardVedioService vipCardVedioService;
    @Autowired
    private IVipCardVedioCommentService vipCardVedioCommentService;
    @Autowired
    private IStoreEmpleeService storeEmpleeService;
    @Autowired
    private IStoreProjectService storeProjectService;
    @Autowired
    private IReserveRecordService reserveRecordService;
    @Autowired
    private IStoreProjectGroupService storeProjectGroupService;
    @Autowired
    private IStockGroupService stockGroupService;

    @Autowired
    private IVipcardDrawRecordService vipcardDrawRecordService;

    @Resource
    private AllVipcardMapper allVipcardMapper;


    // --------------------------------------- 首页 ---------------------------------------

    /**
     * 获取店铺信息
     */
    @ApiOperation(value = "获取店铺信息", notes = "获取店铺信息")
    @GetMapping("/getStore")
    public Result<?> getStore(@RequestParam("storeId") String storeId) {

        StoreInfo si = storeInfoService.getById(storeId);
        double[] storeLngLat = CoordinateTransform.transformBD09ToGCJ02(si.getLng().doubleValue(), si.getLat().doubleValue());
        si.setLng(BigDecimal.valueOf(storeLngLat[0]));
        si.setLat(BigDecimal.valueOf(storeLngLat[1]));
        Date storeExpiryDate = si.getStoreExpiryDate();
        if (storeExpiryDate.compareTo(new Date()) < 0) {
            return Result.OK("店铺已过期，无法继续操作");
        }
        Map<String, Object> map = new HashMap<>();
        try {
            map = org.jeecg.modules.util.BeanUtils.bean2Map(si);
        } catch (Exception e) {

        }

        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        map.put("businessStart", sdf.format(si.getBusinessStart()));
        map.put("businessEnd", sdf.format(si.getBusinessEnd()));

        return Result.OK(map);
    }

    // --------------------------------------- 商城 ---------------------------------------

    /**
     * 商品分类列表
     * 参数：*storeId
     */
    @ApiOperation(value = "商品分类列表", notes = "商品分类列表")
    @PostMapping("/listCommodityGroup")
    public Result<?> listCommodityGroup(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        if (StringUtils.isEmpty(storeId)) {
            return Result.error("参数不全");
        }

        List<CommodityGroup> list = commodityGroupService.list(new QueryWrapper<CommodityGroup>()
                .eq("store_id", storeId).orderByDesc("weight"));
        return Result.OK(list);
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "视频贵宾卡-通过vedioId查询视频(包括评论)")
    @ApiOperation(value = "视频贵宾卡-通过vedioId查询视频(包括评论)", notes = "视频贵宾卡-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryVedioById(@RequestParam(name = "id", required = true) String id) {
        VipCardVedio vedio = vipCardVedioService.getById(id);
        if (vedio == null) {
            return Result.error("未找到对应数据");
        }


        Map<String, Object> map = convertVedio2Map(vedio);

        return Result.OK(map);
    }

    @NotNull
    private Map<String, Object> convertVedio2Map(VipCardVedio vedio) {
        Map<String, Object> map = null;
        try {
            map = org.jeecg.modules.util.BeanUtils.bean2Map(vedio);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


        int praiseNum = vedio.getPraiseNum();
        if (praiseNum > 10000) {
            map.put("praiseNum", NumUtils.convert(praiseNum));
        }
        int commentNum = vedio.getCommentNum();
        if (commentNum > 10000) {
            map.put("commentNum", NumUtils.convert(commentNum));
        }
        int forwardNum = vedio.getForwardNum();
        if (forwardNum > 10000) {
            map.put("forwardNum", NumUtils.convert(forwardNum));
        }

        List list = vipCardVedioCommentService.list(new QueryWrapper<VipCardVedioComment>()
                .eq("vedio_id", vedio.getId()));

        List<AllVipcard> list1 = allVipcardService.list(new QueryWrapper<AllVipcard>()
                .eq("vedio_id", vedio.getId()));
        if (list1.size() > 0) {
            AllVipcard allVipcard = list1.get(0);
            map.put("vipCardName", allVipcard.getCardName());
            map.put("vipCardDetailUrl", allVipcard.getDetailsUrl());
        }

        return map;
    }

    /**
     * 视频贵宾卡-通过vedioId点赞数加1
     *
     * @param id
     * @return
     */
    @AutoLog(value = "视频贵宾卡-通过vedioId点赞数加1")
    @ApiOperation(value = "视频贵宾卡-通过vedioId点赞数加1", notes = "视频贵宾卡-通过vedioId点赞数加1")
    @GetMapping(value = "/addPraiseNum")
    public Result<?> addPraiseNum(@RequestParam(name = "id", required = true) String id) {
        VipCardVedio vipCardVedio = vipCardVedioService.getById(id);

        if (vipCardVedio == null) {
            return Result.error("未找到对应数据");
        }
        int num = vipCardVedio.getPraiseNum();
        appService.updatePraiseNumById(++num, vipCardVedio.getId());
        return Result.OK();
    }

    /**
     * 视频贵宾卡-通过vedioId转发数加1
     *
     * @param id
     * @return
     */
    @AutoLog(value = "视频贵宾卡-通过vedioId转发数加1")
    @ApiOperation(value = "视频贵宾卡-通过vedioId转发数加1", notes = "视频贵宾卡-通过vedioId转发数加1")
    @GetMapping(value = "/addForwardNum")
    public Result<?> addForwardNum(@RequestParam(name = "id", required = true) String id) {
        VipCardVedio vipCardVedio = vipCardVedioService.getById(id);

        if (vipCardVedio == null) {
            return Result.error("未找到对应数据");
        }
        int num = vipCardVedio.getForwardNum();

        appService.updateForwardNumById(++num, vipCardVedio.getId());

        return Result.OK();
    }


    /**
     * 商品列表
     * 参数：*storeId, *groupId, memberId, keyword
     */
    @ApiOperation(value = "商品列表)", notes = "商品列表")
    @PostMapping("/listCommodity")
    public Result<?> listCommodity(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(groupId)) {
            return Result.error("参数不全");
        }
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String keyword = map.get("keyword") == null ? null : String.valueOf(map.get("keyword"));

        List<CommodityManagement> list = commodityManagementService.list(new QueryWrapper<CommodityManagement>()
                .eq("store_id", storeId)
                .eq("group_id", groupId)
                .eq("status", "1")
//                .eq("show_xcx", "1")
                .eq("is_show", "1")
                .like(keyword != null, "trade_name", keyword)
                .orderByDesc("weight"));

        List<Map<String, Object>> result = list.stream().map(c -> {
            Map<String, Object> m = ToolsUtils.objectToMap(c);


            if (memberId == null) {
                m.put("cartNum", 0);
                return m;
            }
            ShopCommodityCart cart = shopCommodityCartService.getOne(new QueryWrapper<ShopCommodityCart>()
                    .eq("commodity_id", c.getId())
                    .eq("member_id", memberId)
                    .eq("store_id", storeId));
            if (cart == null) {
                m.put("cartNum", 0);
            } else {
                m.put("cartNum", cart.getQty());
            }
            return m;
        }).collect(Collectors.toList());
        return Result.OK(result);
    }

    /**
     * 商品列表
     * 参数：*storeId, groupId, memberId, keyword
     */
    @ApiOperation(value = "商品列表)", notes = "商品列表")
    @PostMapping("/listCommodity2")
    public Result<?> listCommodity2(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        if (StringUtils.isEmpty(storeId)) {
            return Result.error("参数不全");
        }
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String keyword = map.get("keyword") == null ? null : String.valueOf(map.get("keyword"));

        List<CommodityManagement> list = commodityManagementService.list(new QueryWrapper<CommodityManagement>()
                .eq("store_id", storeId)
                .eq("status", "1")
                .eq("show_xcx", "1").eq("is_show", "1")
                .like(keyword != null, "trade_name", keyword)
                .orderByDesc("weight"));

        List<Map<String, Object>> result = list.stream().map(c -> {
            Map<String, Object> m = ToolsUtils.objectToMap(c);


            if (memberId == null) {
                m.put("cartNum", 0);
                return m;
            }
            ShopCommodityCart cart = shopCommodityCartService.getOne(new QueryWrapper<ShopCommodityCart>()
                    .eq("commodity_id", c.getId())
                    .eq("member_id", memberId)
                    .eq("store_id", storeId));
            if (cart == null) {
                m.put("cartNum", 0);
            } else {
                m.put("cartNum", cart.getQty());
            }
            return m;
        }).collect(Collectors.toList());
        return Result.OK(result);
    }

    /**
     * 项目分类列表
     * 参数：*storeId
     */
    @ApiOperation(value = "项目分类列表", notes = "项目分类列表")
    @PostMapping("/listProjectGroup")
    public Result<?> listProjectGroup(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        if (StringUtils.isEmpty(storeId)) {
            return Result.error("参数不全");
        }

        List<ProjectGroup> list = projectGroupService.list(new QueryWrapper<ProjectGroup>()
                .eq("store_id", storeId).orderByDesc("weight"));
        return Result.OK(list);
    }

    /**
     * 项目列表
     * 参数：*storeId, *groupId, memberId, keyword
     */
    @PostMapping("/listProject")
    @ApiOperation(value = "项目列表", notes = "项目列表")
    public Result<?> listProject(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(groupId)) {
            return Result.error("参数不全");
        }
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String keyword = map.get("keyword") == null ? null : String.valueOf(map.get("keyword"));

        List<ProjectManagement> list = projectManagementService.list(new QueryWrapper<ProjectManagement>()
                .eq("store_id", storeId)
                .eq("group_id", groupId)
                .eq("is_activate", "1").eq("is_show", "1")
                .like(keyword != null, "project_name", keyword)
                .orderByDesc("project_weight"));

        List<Map<String, Object>> result = list.stream().map(p -> {
            Map<String, Object> m = ToolsUtils.objectToMap(p);

            if (memberId == null) {
                m.put("cartNum", 0);
                return m;
            }
            ShopProjectCart cart = shopProjectCartService.getOne(new QueryWrapper<ShopProjectCart>()
                    .eq("project_id", p.getId())
                    .eq("member_id", memberId)
                    .eq("store_id", storeId));
            if (cart == null) {
                m.put("cartNum", 0);
            } else {
                m.put("cartNum", cart.getQty());
            }
            return m;
        }).collect(Collectors.toList());
        return Result.OK(result);
    }

    /**
     * 项目列表
     * 参数：*storeId, *groupId, memberId, keyword
     */
    @PostMapping("/listProject2")
    @ApiOperation(value = "项目列表", notes = "项目列表")
    public Result<?> listProject2(@RequestBody Map<String, Object> map) {

        System.out.println("map");
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        if (StringUtils.isEmpty(storeId)) {
            return Result.error("参数不全");
        }
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String keyword = map.get("keyword") == null ? null : String.valueOf(map.get("keyword"));

        List<ProjectManagement> list = projectManagementService.list(new QueryWrapper<ProjectManagement>()
                .eq("store_id", storeId)
                .eq("is_activate", "1").eq("is_show", "1")
                .like(keyword != null, "project_name", keyword)
                .orderByDesc("project_weight"));

        List<Map<String, Object>> result = list.stream().map(p -> {
            Map<String, Object> m = ToolsUtils.objectToMap(p);

            if (memberId == null) {
                m.put("cartNum", 0);
                return m;
            }
            ShopProjectCart cart = shopProjectCartService.getOne(new QueryWrapper<ShopProjectCart>()
                    .eq("project_id", p.getId())
                    .eq("member_id", memberId)
                    .eq("store_id", storeId));
            if (cart == null) {
                m.put("cartNum", 0);
            } else {
                m.put("cartNum", cart.getQty());
            }
            return m;
        }).collect(Collectors.toList());
        return Result.OK(result);
    }

    /**
     * 项目列表
     * 参数：*storeId, *projectId
     */
    @ApiOperation(value = "项目列表", notes = "项目列表")
    @PostMapping("/projectDetail")
    public Result<?> projectDetail(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String projectId = map.get("projectId") == null ? null : String.valueOf(map.get("projectId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(projectId)) {
            return Result.error("参数不全");
        }
        ProjectManagement project = projectManagementService.getById(projectId);
        List<Map<String, Object>> serveList = projectManagementService.serveList(storeId, projectId);
        List<Map<String, Object>> shopList = projectManagementService.shopList(storeId, projectId);

        Map<String, Object> result = new HashMap<>();
        result.put("project", project);
        result.put("serveList", serveList);
        result.put("shopList", shopList);
        return Result.OK(result);
    }

    /**
     * 优惠券列表（根据已选择的优惠券判断其他优惠券是否还可继续叠加）
     * 参数：*storeId, *memberId, *totalAmount, *useMemberDiscount, couponList[]
     * couponList[]: *id, *num
     */
    @ApiOperation(value = "优惠券列表", notes = "优惠券列表")
    @PostMapping("/listCoupon")
    public Result<?> listCoupon(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String totalCanUseDiscountAmountStr = map.get("totalCanUseDiscountAmount") == null ? null : String.valueOf(map.get("totalCanUseDiscountAmount"));
        String useMemberDiscountSt = map.get("useMemberDiscount") == null ? null : String.valueOf(map.get("useMemberDiscount"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(totalCanUseDiscountAmountStr) || StringUtils.isEmpty(useMemberDiscountSt)) {
            return Result.error("参数不全");
        }
        List<Map<String, Object>> couponList = map.get("couponList") == null ? new ArrayList<>() : (List<Map<String, Object>>) map.get("couponList");

        List<Map<String, Object>> listCoupon1 = cashierService.listCoupon1(map);
        List<Map<String, Object>> listCoupon2 = cashierService.listCoupon2(map);
        List<Map<String, Object>> listCoupon3 = cashierService.listCoupon3(map);
        List<Map<String, Object>> result = new ArrayList<>();

        if (couponList.size() == 0) {
            listCoupon1.forEach(m -> m.put("disabled", false));
            result.addAll(listCoupon1);
            result.addAll(listCoupon2);
            result.addAll(listCoupon3);
            return Result.OK(result);
        }
        for (Map<String, Object> m : couponList) {
            boolean couponInList1 = false;
            Map<String, Object> coupon = null;
            for (Map<String, Object> m1 : listCoupon1) {
                if (String.valueOf(m.get("id")).equals(String.valueOf(m1.get("id")))) {
                    coupon = m1;
                    couponInList1 = true;
                }
            }
            if (!couponInList1) {
                return Result.error("使用了不可用的优惠劵，请重新选择");
            }
            int num = m.get("num") == null ? 0 : Integer.parseInt(String.valueOf(m.get("num")));
            int couponNum = coupon.get("num") == null ? 0 : Integer.parseInt(String.valueOf(coupon.get("num")));
            if (num > couponNum) {
                return Result.error("优惠劵：" + coupon.get("ticketName") + "，使用数量超过持有数量，请重新选择");
            }
        }

        List<Map<String, Object>> checkedCoupons = listCoupon1.stream().filter(o -> {
            for (Map<String, Object> m : couponList) {
                if (String.valueOf(o.get("id")).equals(String.valueOf(m.get("id")))) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());

        listCoupon1 = listCoupon1.stream().map(m -> {
            String id = m.get("id") == null ? "" : String.valueOf(m.get("id"));
            String ticketType = m.get("ticketType") == null ? "" : String.valueOf(m.get("ticketType"));
            String isSelectNext = m.get("isSelectNext") == null ? "" : String.valueOf(m.get("isSelectNext"));
            String isSelect = m.get("isSelect") == null ? "" : String.valueOf(m.get("isSelect"));
            m.put("disabled", false);
            if ("1".equals(ticketType)) {
                // 礼品劵
                // 是否可与自身叠加
                boolean overlyingSelf = "0".equals(isSelectNext);
                // 是否可与其他劵叠加
                boolean overlyingOther = "0".equals(isSelect);
                if (!overlyingSelf) {
                    // 已选的自身
                    Map<String, Object> self = checkedCoupons.stream()
                            .filter(o2 -> id.equals(String.valueOf(o2.get("id"))))
                            .findFirst().orElse(null);
                    if (self != null) {
                        int num = m.get("num") == null ? 0 : (Integer) m.get("num");
                        if (num > 1) {
                            m.put("reason", "该劵不能与自身叠加使用，仅能选择1张");
                        }
                    }
                }
                if (!overlyingOther) {
                    // 已选的其他劵的数量
                    long count = checkedCoupons.stream()
                            .filter(o2 -> !id.equals(String.valueOf(o2.get("id"))))
                            .count();
                    if (count > 0) {
                        m.put("disabled", true);
                        m.put("reason", "该劵不能与其他劵叠加使用");
                    }
                }
            }
            return m;
        }).collect(Collectors.toList());

        result.addAll(listCoupon1);
        result.addAll(listCoupon2);
        result.addAll(listCoupon3);
        return Result.OK(result);
    }

    /**
     * 可用优惠券列表（根据优惠券使用条件）
     * 参数：*storeId, *memberId, *totalAmount
     */
    @ApiOperation(value = "可用优惠券列表", notes = "可用优惠券列表")
    @PostMapping("/listCoupon1")
    public Result<?> listCoupon1(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String totalCanUseDiscountAmountStr = map.get("totalCanUseDiscountAmount") == null ? null : String.valueOf(map.get("totalCanUseDiscountAmount"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(totalCanUseDiscountAmountStr)) {
            return Result.error("参数不全");
        }

        return Result.OK(cashierService.listCoupon1(map));
    }

    /**
     * 不可用优惠券列表（根据优惠券使用条件）
     * 参数：*storeId, *memberId, *totalAmount
     */
    @ApiOperation(value = "不可用优惠券列表", notes = "不可用优惠券列表")
    @PostMapping("/listCoupon2")
    public Result<?> listCoupon2(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String totalCanUseDiscountAmountStr = map.get("totalCanUseDiscountAmount") == null ? null : String.valueOf(map.get("totalCanUseDiscountAmount"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(totalCanUseDiscountAmountStr)) {
            return Result.error("参数不全");
        }

        return Result.OK(cashierService.listCoupon2(map));
    }

    /**
     * 已失效优惠券列表（根据优惠券使用条件）
     * 参数：*storeId, *memberId
     */
    @ApiOperation(value = "已失效优惠券列表", notes = "已失效优惠券列表")
    @PostMapping("/listCoupon3")
    public Result<?> listCoupon3(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }

        return Result.OK(cashierService.listCoupon3(map));
    }

    /**
     * 计算总价、优惠金额（根据优惠券使用情况计算总优惠及各商品优惠）
     * 参数：*storeId, *memberId, *useMemberDiscount(是否使用会员折扣), *memberDiscount(会员折扣), *commodityList[](商品列表), couponList[](优惠券id列表)
     * couponList[]: *id, *num
     * commodityList：*id(商品/项目id), *type(1.商品2.项目), *count(个数)
     */
    @ApiOperation(value = "计算总价、优惠金额", notes = "计算总价、优惠金额")
    @PostMapping("/compute")
    public Result<?> compute(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String useMemberDiscount = map.get("useMemberDiscount") == null ? null : String.valueOf(map.get("useMemberDiscount"));
        List<Map<String, Object>> commodityList = (List<Map<String, Object>>) map.get("commodityList");
        List<Map<String, Object>> couponList = (List<Map<String, Object>>) map.get("couponList");
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(useMemberDiscount) || CollectionUtils.isEmpty(commodityList)) {
            return Result.error("参数不全");
        }

        return Result.OK(cashierService.compute2(map));
    }

    /**
     * 订单保存（开单）
     * 参数：*storeId, *memberId, *totalAmount(订单金额), *totalDiscountAmount(优惠金额), *realAmount(实付金额)
     * , *commodityList[](商品列表), couponList[](优惠券id列表), remark(备注)
     * , *useMemberDiscount(是否使用会员折扣), *memberDiscount(会员折扣)
     * couponList[]: 与listCoupon接口返回值一致(只传被使用的优惠劵)
     * commodityList：与compute接口返回值一致
     */
    @ApiOperation(value = "订单保存（开单）", notes = "订单保存（开单）")
    @PostMapping("/saveOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> saveOrder(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String totalAmount = map.get("totalAmount") == null ? null : String.valueOf(map.get("totalAmount"));
        String totalDiscountAmount = map.get("totalDiscountAmount") == null ? null : String.valueOf(map.get("totalDiscountAmount"));
        String realAmount = map.get("realAmount") == null ? null : String.valueOf(map.get("realAmount"));
        List<Map<String, Object>> commodityList = (List<Map<String, Object>>) map.get("commodityList");
        String useMemberDiscountStr = map.get("useMemberDiscount") == null ? null : String.valueOf(map.get("useMemberDiscount"));
        String memberDiscountStr = map.get("memberDiscount") == null ? null : String.valueOf(map.get("memberDiscount"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(totalAmount) || StringUtils.isEmpty(totalDiscountAmount) || StringUtils.isEmpty(realAmount) || CollectionUtils.isEmpty(commodityList) || StringUtils.isEmpty(useMemberDiscountStr) || StringUtils.isEmpty(memberDiscountStr)) {
            log.info("saveOrder:参数不全");
            return Result.error("参数不全");
        }
        List<Map<String, Object>> couponList = map.get("couponList") == null ? new ArrayList<>() : (List<Map<String, Object>>) map.get("couponList");
        String remark = map.get("remark") == null ? null : String.valueOf(map.get("remark"));
        BigDecimal realAmountDecimal = new BigDecimal(realAmount);
        boolean useMemberDiscount = "1".equals(useMemberDiscountStr);
        BigDecimal memberDiscount = memberDiscountStr == null ? BigDecimal.TEN : new BigDecimal(memberDiscountStr);

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            log.info("saveOrder:店铺不存在");
            return Result.error("店铺不存在");
        }
        String xcxAppId = store.getXcxAppId();
        if (StringUtils.isEmpty(xcxAppId)) {
            log.info("saveOrder:店铺还未绑定小程序");
            return Result.error("店铺还未绑定小程序");
        }
        String saobeiMerchantNo = store.getSaobeiMerchantNo();
        String saobeiTerminalId = store.getSaobeiTerminalId();
        String saobeiAccessToken = store.getSaobeiAccessToken();
        if (StringUtils.isEmpty(saobeiMerchantNo) || StringUtils.isEmpty(saobeiTerminalId) || StringUtils.isEmpty(saobeiAccessToken)) {
            log.info("saveOrder:店铺还未绑定支付");
            return Result.error("店铺还未绑定支付");
        }

        MemberManagement mm = memberManagementService.getById(memberId);
        String xcxOpenId = mm.getXcxOpenId();
        if (StringUtils.isEmpty(xcxOpenId)) {
            log.info("saveOrder:会员还未绑定小程序");
            return Result.error("会员还未绑定小程序");
        }
//TODO Lukas
        BaseOrder order = new BaseOrder();
        order.setOrderCode(ToolsUtils.getBillNo("LO"));
        order.setOrderType("02");
        order.setOrderStatus("0");
        order.setStoreId(storeId);
        order.setStoreName(storeInfoService.getById(storeId).getStoreName());
        order.setMemberId(memberId);
        order.setMemberName(mm.getName());
        order.setMemberPhone(mm.getPhone());
        order.setMemberNickName(mm.getNickName());
        order.setMemberHeadPortrait(mm.getHeadPortrait());
        order.setMemberLevel(levelSetService.getById(mm.getLevelId()).getRankName());
        order.setTotalAmount(Double.parseDouble(totalAmount));
        order.setTotalDiscountAmount(Double.parseDouble(totalDiscountAmount));
        order.setRealAmount(Double.parseDouble(realAmount));
        order.setMemberDiscount(useMemberDiscount ? memberDiscount.toString() : "未使用会员/股东折扣");
        order.setReduction(0.00);
        order.setWeixinAmount(0.00);
        order.setWeixinAccount(0.00);
        order.setZhifubaoAmount(0.00);
        order.setZhifubaoAccount(0.00);
        order.setBalanceAmount(0.00);
        order.setStockBalanceAmount(0.00);
        order.setChargeAmount(0.00);
        order.setRemark(remark);
        order.setOrderJsonStr(JSON.toJSONString(map));
        baseOrderService.save(order);

        for (Map<String, Object> m : couponList) {
            String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
            String numStr = m.get("nums") == null ? "0" : String.valueOf(m.get("nums"));
            log.info("优惠券减掉数量：" + numStr);
            int num = Integer.parseInt(numStr);
            BaseMemberVipCoupon bmvc = baseMemberVipCouponService.getById(id);
            if (num > bmvc.getNum()) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                log.info("saveOrder:优惠劵使用数量超出了持有数量");
                return Result.error("优惠劵名称：" + bmvc.getTicketName() + "，优惠劵使用数量超出了持有数量");
            }
            bmvc.setNum(bmvc.getNum() - num);
            baseMemberVipCouponService.updateById(bmvc);
        }

        // 出库记录明细
        List<OutStorageDetail> outStorageDetailList = new ArrayList<>();
        // 出入库明
        List<StorageOutinDetail> storageOutinDetailList = new ArrayList<>();

        for (Map<String, Object> m : commodityList) {
            String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
            String type = m.get("type") == null ? null : String.valueOf(m.get("type"));
            String countStr = m.get("count") == null ? "0" : String.valueOf(m.get("count"));
            BigDecimal count = new BigDecimal(countStr);
            String name = m.get("name") == null ? "0" : String.valueOf(m.get("name"));
            String specification = m.get("specification") == null ? "0" : String.valueOf(m.get("specification"));
            String price = m.get("price") == null ? "0" : String.valueOf(m.get("price"));
            String totalPrice = m.get("totalPrice") == null ? "0" : String.valueOf(m.get("totalPrice"));
            String discountAmount = m.get("discountAmount") == null ? "0" : String.valueOf(m.get("discountAmount"));
            String free = m.get("free") == null ? "0" : String.valueOf(m.get("free"));
            String pic = m.get("pic") == null ? "0" : String.valueOf(m.get("pic"));
            String staffId = m.get("staffId") == null ? "0" : String.valueOf(m.get("staffId"));

            BigDecimal totalPriceDecimal = new BigDecimal(totalPrice);
            BigDecimal discountAmountDecimal = new BigDecimal(discountAmount);
            BigDecimal realTotalPrice = totalPriceDecimal.subtract(discountAmountDecimal);

            if ("1".equals(type)) {
                // ------------------------- 商品 -------------------------
                CommodityManagement cm = commodityManagementService.getById(id);
                if (cm == null) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    log.info("saveOrder:选择了不存在的商品");
                    return Result.error("选择了不存在的商品");
                }
                if (cm.getInventory() < count.intValue()) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    log.info("saveOrder:商品：" + cm.getTradeName() + "库存不足（剩余" + cm.getInventory() + "个），请重新选择商品");
                    return Result.error("商品：" + cm.getTradeName() + "库存不足（剩余" + cm.getInventory() + "个），请重新选择商品");
                }
                cm.setInventory(cm.getInventory() - count.intValue());
                if (cm.getInventory() == 0) {
                    cm.setStatus("2");
                    // 模板消息
                    try {
                        if (store != null) {
                            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
                            String xcxAppSecret = store.getXcxAppSecret();
                            if (bossGzhOpenId == null) {
                                log.info("库存不足提醒模板推送失败，老板未绑定公众号");
                            } else {
                                if (store == null) {
                                    log.info("库存不足提醒模板推送失败，未查到店铺信息");
                                } else {
                                    String gzhAppId = store.getGzhAppId();
                                    String gzhAppSecret = store.getGzhAppSecret();
                                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                        log.info("库存不足提醒模板推送失败，店铺未绑定公众号");
                                    } else {
                                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                        String result1 = HttpUtils.sendGet(url1);
                                        JSONObject resultJson1 = JSON.parseObject(result1);
                                        String errcode = resultJson1.getString("errcode");
                                        if (errcode != null && !"0".equals(errcode)) {
                                            log.info("库存不足提醒模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                        } else {
                                            String accessToken = resultJson1.getString("access_token");
                                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("库存不足提醒", storeId);
                                            String templateId = msgTemplate.getTemplateId();
                                            util.inventoryInsufficientNotice(templateId, bossGzhOpenId, cm.getTradeName(), String.valueOf(cm.getInventory()), sdf.format(new Date()), xcxAppId, "", accessToken);
                                            log.info("库存不足提醒模板推送成功");
                                        }
                                    }
                                }
                            }
                        }

                    } catch (Exception e) {
                        log.error("库存不足提醒模板推送失败，发生异常", e);
                    }
                }
                commodityManagementService.updateById(cm);


                m.put("pic", cm.getProductPic());
                m.put("detailsUrl", cm.getDetailsUrl());

                // 出库记录明细
                OutStorageDetail outStorageDetail = new OutStorageDetail();
                outStorageDetail.setCommodityId(id);
                outStorageDetail.setCommodityName(cm.getTradeName());
                outStorageDetail.setCommoditySpecs(cm.getSpecification());
                outStorageDetail.setOutQty(count.intValue());
                outStorageDetail.setStoreId(storeId);
                outStorageDetailList.add(outStorageDetail);

                // 出入库明细
                StorageOutinDetail storageOutinDetail = new StorageOutinDetail();
                storageOutinDetail.setCommodityName(cm.getTradeName());
                storageOutinDetail.setCommodityId(cm.getId());
                storageOutinDetail.setOperateType("出库操作");
                storageOutinDetail.setOutinQty(count.intValue());
                storageOutinDetail.setRemainQty(cm.getInventory());
                storageOutinDetail.setBillTime(new Date());
                storageOutinDetail.setOperator("线上购买");
                storageOutinDetail.setStoreId(storeId);
                storageOutinDetailList.add(storageOutinDetail);
            } else {
                // ------------------------- 项目 -------------------------
                ProjectManagement pm = projectManagementService.getById(id);
                if (pm == null) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    log.info("saveOrder:选择了不存在的项目");
                    return Result.error("选择了不存在的项目");
                }

                m.put("pic", pm.getProjectPic());
                m.put("detailsUrl", pm.getDetailsUrl());
            }
        }
        order.setCommodityListJsonStr(JSON.toJSONString(commodityList));
        order.setCouponListJsonStr(JSON.toJSONString(couponList));

        if (outStorageDetailList.size() > 0) {
            OutStorageMain outStorageMain = new OutStorageMain();
            String billNo = ToolsUtils.getBillNo("OS");
            outStorageMain.setBillNo(billNo);
            outStorageMain.setOutType("01");
            outStorageMain.setBillTime(new Date());
            outStorageMain.setPreparer("线上购买");
            outStorageMain.setStoreId(storeId);
            outStorageMainService.save(outStorageMain);
            for (OutStorageDetail outStorageDetail : outStorageDetailList) {
                outStorageDetail.setMainId(outStorageMain.getId());
                outStorageDetail.setBillNo(billNo);
                outStorageDetail.setOutinType("01");
                outStorageDetailService.save(outStorageDetail);
            }
            for (StorageOutinDetail storageOutinDetail : storageOutinDetailList) {
                storageOutinDetail.setBillNo(billNo);
                storageOutinDetail.setOutinType("01");
                storageOutinDetailService.save(storageOutinDetail);
            }
        }

        order.setStaffPercentage(0.0);
        order.setStockPercentage(0.0);
        order.setDriveTurnoverAll(0.0);
        order.setStaffShareMoney(0.0);
        baseOrderService.updateById(order);

        // 订单支付后清空购物车
        shopCommodityCartService.remove(new QueryWrapper<ShopCommodityCart>().eq("member_id", memberId));
        shopProjectCartService.remove(new QueryWrapper<ShopProjectCart>().eq("member_id", memberId));

        String totalFee = String.valueOf(realAmountDecimal.multiply(new BigDecimal("100")).intValue());

        SaobeiMiniPayResponse minipayResponse = Saobei.minipay(saobeiAccessToken, saobeiMerchantNo, saobeiTerminalId, xcxAppId, xcxOpenId, "小程序订单", order.getId(), totalFee);
        if ("01".equals(minipayResponse.getResult_code())) {
            SaobeiOrderRecord saobeiOrderRecord = new SaobeiOrderRecord();
            saobeiOrderRecord.setType("5");
            saobeiOrderRecord.setOutTradeNo(minipayResponse.getOut_trade_no());
            saobeiOrderRecord.setTerminalTrace(order.getId());
            saobeiOrderRecord.setTotalFee(totalFee);
            saobeiOrderRecord.setStoreId(storeId);
            saobeiOrderRecord.setCreateBy("xcx");
            saobeiOrderRecordService.save(saobeiOrderRecord);

            Map<String, Object> payParams = new HashMap<>();
            payParams.put("timeStamp", minipayResponse.getTimeStamp());
            payParams.put("nonceStr", minipayResponse.getNonceStr());
            payParams.put("package_str", minipayResponse.getPackage_str());
            payParams.put("signType", minipayResponse.getSignType());
            payParams.put("paySign", minipayResponse.getPaySign());

            order.setPayParamsStr(JSON.toJSONString(payParams));
            baseOrderService.updateById(order);

            Map<String, Object> result = ToolsUtils.objectToMap(order);
            result.put("payParams", payParams);
            return Result.OK(result);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.info("saveOrder:生成扫呗订单失败：" + minipayResponse.getReturn_msg());
            return Result.error("生成扫呗订单失败：" + minipayResponse.getReturn_msg());
        }
    }

    @Autowired
    private BalanceChangeRecordMapper balanceChangeRecordMapper;
    /**
     * 订单支付后的逻辑处理
     * 参数：*orderId, *payType(付款方式，中文), balanceAmount(选择其他支付方式时，使用一部分会员余额), stockBalanceAmount(选择其他支付方式时，使用一部分股本余额)
     */
    @ApiOperation(value = "订单支付后的逻辑处理", notes = "订单支付后的逻辑处理")
    @PostMapping("/payOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> payOrder(@RequestBody Map<String, Object> params) {

        log.info("payOrder, params = {}", params);

        String orderId = params.get("orderId") == null ? null : String.valueOf(params.get("orderId"));
        String payType = params.get("payType") == null ? null : String.valueOf(params.get("payType"));
        if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(payType)) {
            return Result.error("参数不全");
        }
        String balanceAmountStr = params.get("balanceAmount") == null ? "0" : String.valueOf(params.get("balanceAmount"));
        BigDecimal balanceAmount = new BigDecimal(balanceAmountStr);
        String stockBalanceAmountStr = params.get("stockBalanceAmount") == null ? "0" : String.valueOf(params.get("stockBalanceAmount"));
        BigDecimal stockBalanceAmount = new BigDecimal(stockBalanceAmountStr);
        String outTradeNo = params.get("outTradeNo") == null ? null : String.valueOf(params.get("outTradeNo"));

        BaseOrder order = baseOrderService.getById(orderId);

        if ("0".equals(order.getOrderStatus())) {
            String storeId = order.getStoreId();
            Map<String, Object> map = (Map<String, Object>) JSON.parse(order.getOrderJsonStr());

            String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
            String totalAmount = map.get("totalAmount") == null ? null : String.valueOf(map.get("totalAmount"));
            String totalDiscountAmount = map.get("totalDiscountAmount") == null ? null : String.valueOf(map.get("totalDiscountAmount"));
            String realAmount = map.get("realAmount") == null ? null : String.valueOf(map.get("realAmount"));
            List<Map<String, Object>> commodityList = (List<Map<String, Object>>) map.get("commodityList");
            String useMemberDiscountStr = map.get("useMemberDiscount") == null ? null : String.valueOf(map.get("useMemberDiscount"));
            String memberDiscountStr = map.get("memberDiscount") == null ? null : String.valueOf(map.get("memberDiscount"));
            List<Map<String, Object>> couponList = map.get("couponList") == null ? new ArrayList<>() : (List<Map<String, Object>>) map.get("couponList");
            String remark = map.get("remark") == null ? null : String.valueOf(map.get("remark"));
            BigDecimal realAmountDecimal = new BigDecimal(realAmount);
            boolean useMemberDiscount = "1".equals(useMemberDiscountStr);
            BigDecimal memberDiscount = memberDiscountStr == null ? BigDecimal.TEN : new BigDecimal(memberDiscountStr);

            MemberManagement mm = memberManagementService.getById(memberId);

            // 参与分红的股东
            StockManage dividendStock = null;

            order.setPayType(payType);
            order.setPayCode(outTradeNo);
            if ("1".equals(mm.getStatus())) {
                dividendStock = stockManageService.getById(mm.getStockId());
                if (dividendStock != null) {
                    order.setStockName(dividendStock.getStockName());
                    MemberManagement dividendStockMember = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("my_stock_id", dividendStock.getId()));
                    order.setStockPhone(dividendStockMember.getPhone());
                }
            }
            switch (payType) {
                case "微信支付":
                    // 先禁用部分余额支付
                    order.setWeixinAmount(Double.parseDouble(realAmount));
                    break;
                case "会员余额支付":
                    order.setBalanceAmount(Double.parseDouble(realAmount));
                    BigDecimal balance = new BigDecimal(String.valueOf(mm.getBalance()));
                    if (realAmountDecimal.compareTo(balance) > 0) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return Result.error("会员余额不足，请选择其他支付方式");
                    }
                    mm.setBalance(balance.subtract(realAmountDecimal).doubleValue());
                    memberManagementService.updateById(mm);
                    //余额变更记录
                    BalanceChangeRecord balanceChangeRecord = new BalanceChangeRecord();
                    balanceChangeRecord.setAmount(realAmountDecimal.doubleValue());
                    balanceChangeRecord.setOldValue(balance.doubleValue());
                    balanceChangeRecord.setNewValue(mm.getBalance());
                    balanceChangeRecord.setOrderNo(order.getOrderCode());
                    balanceChangeRecord.setChangeCode("X");
                    balanceChangeRecord.setMemberId(mm.getId());
                    balanceChangeRecord.setMemberName(mm.getName());
                    balanceChangeRecord.setMemberPhone(mm.getPhone());
                    balanceChangeRecord.setStoreId(mm.getStoreId());
                    balanceChangeRecord.setTradeMode("会员余额支付");
                    balanceChangeRecord.setTradeTime(new Date());
                    balanceChangeRecord.setBalanceType("M");
                    balanceChangeRecordMapper.insert(balanceChangeRecord);
                    break;
                case "股本余额支付":
                    order.setStockBalanceAmount(Double.parseDouble(realAmount));
                    StockManage sm = stockManageService.getById(mm.getMyStockId());
                    if (sm == null) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return Result.error("当前客户不是股东，不可使用股东余额支付");
                    }
                    BigDecimal equityBalance = new BigDecimal(String.valueOf(sm.getEquityBalance()));
                    BigDecimal stockLowest = new BigDecimal(String.valueOf(sm.getStockLowest()));
                    if (equityBalance.subtract(realAmountDecimal).compareTo(stockLowest) < 0) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return Result.error("股本余额不足以支付订单（股本最低限额：" + sm.getStockLowest() + "元），请选择其他支付方式");
                    }
                    sm.setEquityBalance(equityBalance.subtract(realAmountDecimal).doubleValue());
                    stockManageService.updateById(sm);
                    break;
            }

            for (Map<String, Object> m : couponList) {
                String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
                String numStr = m.get("nums") == null ? "0" : String.valueOf(m.get("nums"));
                int num = Integer.parseInt(numStr);
                BaseMemberVipCoupon bmvc = baseMemberVipCouponService.getById(id);

                // 处理优惠劵使用情况、发卡记录到店情况
                BaseMemberVip bmv = baseMemberVipService.getById(bmvc.getMemberVipId());
                if ("0".equals(bmv.getUsed())) {
                    bmv.setUsed("1");
                    baseMemberVipService.updateById(bmv);
                    IssuingRecords ir = issuingRecordsService.getById(bmv.getIssuingRecordsId());
                    if (ir != null) {
                        ir.setToStoreNum(ir.getToStoreNum() + 1);
                        issuingRecordsService.updateById(ir);
                    }
                }
            }
            // 订单总员工销售提成
            BigDecimal commissionMoneyAll = BigDecimal.ZERO;
            // 订单总股东分红
            BigDecimal dividendMoneyAll = BigDecimal.ZERO;
            // 订单总带动营业额
            BigDecimal driveTurnoverAll = BigDecimal.ZERO;

            boolean orderHasCommodity = false;
            List<BaseSelfOrderCommodity> bsocList = new ArrayList<>();

            for (Map<String, Object> m : commodityList) {
                String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
                String type = m.get("type") == null ? null : String.valueOf(m.get("type"));
                String countStr = m.get("count") == null ? "0" : String.valueOf(m.get("count"));
                BigDecimal count = new BigDecimal(countStr);
                String name = m.get("name") == null ? "0" : String.valueOf(m.get("name"));
                String specification = m.get("specification") == null ? "0" : String.valueOf(m.get("specification"));
                String price = m.get("price") == null ? "0" : String.valueOf(m.get("price"));
                String totalPrice = m.get("totalPrice") == null ? "0" : String.valueOf(m.get("totalPrice"));
                String discountAmount = m.get("discountAmount") == null ? "0" : String.valueOf(m.get("discountAmount"));
                String free = m.get("free") == null ? "0" : String.valueOf(m.get("free"));
                String pic = m.get("pic") == null ? "0" : String.valueOf(m.get("pic"));
                String staffId = m.get("staffId") == null ? "0" : String.valueOf(m.get("staffId"));

                BigDecimal totalPriceDecimal = new BigDecimal(totalPrice);
                BigDecimal discountAmountDecimal = new BigDecimal(discountAmount);
                BigDecimal realTotalPrice = totalPriceDecimal.subtract(discountAmountDecimal);

                // 拿销售提成的员工
                StaffManagement xiaoshouStaff = staffManagementService.getById(staffId);

                if ("1".equals(type)) {
                    // ------------------------- 商品 -------------------------
                    orderHasCommodity = true;

                    CommodityManagement cm = commodityManagementService.getById(id);

                    BaseOrderCommodity boc = new BaseOrderCommodity();
                    boc.setOrderId(order.getId());
                    boc.setCommodityId(id);
                    boc.setCommodityName(name);
                    boc.setCommoditySpecs(specification);
                    boc.setCommodityQty(countStr);
                    boc.setUnitPrice(price);
                    boc.setTotalPrice(totalPrice);
                    boc.setPreferAmount(discountAmount);
                    boc.setGiveFlag(free);
                    boc.setPic(pic);
                    boc.setStoreId(storeId);
                    boc.setCommodityJsonStr(JSON.toJSONString(cm));
                    if (xiaoshouStaff != null) {
                        // 员工提成
                        boc.setCommissionOwner(staffId);
                        boc.setCommissionOwnerName(xiaoshouStaff.getName());
                        BigDecimal rewardRate;
                        BaseStaffStatusSpecial bsss = baseStaffStatusSpecialService.getOne(new QueryWrapper<BaseStaffStatusSpecial>()
                                .eq("staff_status_id", xiaoshouStaff.getEmployeeId())
                                .eq("type", "1")
                                .eq("shop_id", id));
                        if (bsss != null) {
                            rewardRate = new BigDecimal(String.valueOf(bsss.getRewardRate()));
                        } else {
                            BaseStaffStatus bss = baseStaffStatusService.getById(xiaoshouStaff.getEmployeeId());
                            rewardRate = new BigDecimal(String.valueOf(bss.getShopReward()));
                        }
                        BigDecimal commissionMoney = realTotalPrice.multiply(rewardRate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                        boc.setCommissionMoney(commissionMoney.doubleValue());
                        commissionMoneyAll = commissionMoneyAll.add(commissionMoney);

                        // 销售提成
                        BigDecimal sellMoney = new BigDecimal(String.valueOf(xiaoshouStaff.getSellMoney()));
                        xiaoshouStaff.setSellMoney(sellMoney.add(commissionMoney).doubleValue());
                        // 累计提成
                        BigDecimal totalDeduction = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalDeduction()));
                        xiaoshouStaff.setTotalDeduction(totalDeduction.add(commissionMoney).doubleValue());
                        // 总业绩
                        BigDecimal totalSall = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSell()));
                        xiaoshouStaff.setTotalSell(totalSall.add(realTotalPrice).doubleValue());
                        // 总薪资
                        BigDecimal totalSalary = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSalary()));
                        xiaoshouStaff.setTotalSalary(totalSalary.add(commissionMoney).doubleValue());
                        staffManagementService.updateById(xiaoshouStaff);
                        m.put("staffId", xiaoshouStaff.getId());
                        m.put("staffName", xiaoshouStaff.getName());
                        m.put("staffCommission", commissionMoney);
                    }
                    if (dividendStock != null) {
                        // 股东分红
                        boc.setDividendOwner(dividendStock.getId());
                        boc.setDividendOwnerName(dividendStock.getStockName());

                        // 价格 * 最低利率限额 = 老板最低获利
                        BigDecimal commodityMinimumMargin = new BigDecimal(String.valueOf(cm.getMinimumMargin()));
                        BigDecimal lowPrice = totalPriceDecimal.multiply(commodityMinimumMargin).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                        // 实际售价 * 毛利率 * 股东分红比例 = 股东分红
                        BigDecimal commodityGrossRate = new BigDecimal(String.valueOf(cm.getGrossRate()));
                        BigDecimal stockProrateDividends = new BigDecimal(String.valueOf(dividendStock.getProrateDividends()));
                        BigDecimal dividendMoney = realTotalPrice.multiply(commodityGrossRate).multiply(stockProrateDividends).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                        // (实际售价 - 股东分红) 应大于 老板最低获利，否则不给股东分红
                        if (lowPrice.compareTo(realTotalPrice.subtract(dividendMoney)) >= 0) {
                            dividendMoney = BigDecimal.ZERO;
                        }
                        boc.setDividendMoney(dividendMoney.doubleValue());
                        dividendMoneyAll = dividendMoneyAll.add(dividendMoney);

                        // 总分红
                        BigDecimal totalDividend = new BigDecimal(String.valueOf(dividendStock.getTotalDividend()));
                        dividendStock.setTotalDividend(totalDividend.add(dividendMoney).doubleValue());
                        // 可提现分红
                        BigDecimal canWithdrawal = new BigDecimal(String.valueOf(dividendStock.getCanWithdrawal()));
                        dividendStock.setCanWithdrawal(canWithdrawal.add(dividendMoney).doubleValue());
                        // 带动营业额
                        BigDecimal driveTurnover = new BigDecimal(String.valueOf(dividendStock.getDriveTurnover()));
                        dividendStock.setDriveTurnover(driveTurnover.add(realTotalPrice).doubleValue());
                        driveTurnoverAll = driveTurnoverAll.add(realTotalPrice);
                        stockManageService.updateById(dividendStock);

                        // 会员带动分红
                        BigDecimal shareholderDividends = new BigDecimal(String.valueOf(mm.getShareholderDividends()));
                        mm.setShareholderDividends(shareholderDividends.add(dividendMoney).doubleValue());
                        memberManagementService.updateById(mm);
                    }
                    // 线上订单生成自提订单
                    BaseSelfOrderCommodity bsoc = new BaseSelfOrderCommodity();
                    BeanUtils.copyProperties(boc, bsoc);
                    bsocList.add(bsoc);
                    baseOrderCommodityService.save(boc);
                    StoreInfo store = storeInfoService.getById(storeId);
                    if (store != null) {
                        String xcxAppId = store.getXcxAppId();
                        String xcxAppSecret = store.getXcxAppSecret();
                        // 模板消息
                        try {
                            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(store.getId());
                            if (bossGzhOpenId == null) {
                                log.info("商家自提订单提醒模板推送失败，老板未绑定公众号");
                            } else {
                                if (store == null) {
                                    log.info("商家自提订单提醒模板推送失败，未查到店铺信息");
                                } else {
                                    String gzhAppId = store.getGzhAppId();
                                    String gzhAppSecret = store.getGzhAppSecret();
                                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                        log.info("商家自提订单提醒模板推送失败，店铺未绑定公众号");
                                    } else {
                                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                        String result1 = HttpUtils.sendGet(url1);
                                        JSONObject resultJson1 = JSON.parseObject(result1);

                                        System.out.println("生成二维码的地址:" + result1);
                                        String errcode = resultJson1.getString("errcode");
                                        if (errcode != null && !"0".equals(errcode)) {
                                            log.info("商家自提订单提醒模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                        } else {
                                            String accessToken = resultJson1.getString("access_token");
                                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("商家自提订单提醒", storeId);
                                            String templateId = msgTemplate.getTemplateId();
                                            util.selfMentionNotice(templateId, bossGzhOpenId, order.getOrderCode(), sdf.format(new Date()), order.getMemberName(), order.getMemberPhone(), xcxAppId, "", accessToken);
                                            log.info("商家自提订单提醒模板推送成功");
                                        }
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.error("商家自提订单提醒板推送失败，发生异常", e);
                        }
                    }

                } else {
                    // ------------------------- 项目 -------------------------
                    ProjectManagement pm = projectManagementService.getById(id);

                    BigDecimal singleTotalPriceDecimal = totalPriceDecimal.divide(count, 2, RoundingMode.HALF_UP);
                    BigDecimal singleDiscountAmountDecimal = discountAmountDecimal.divide(count, 2, RoundingMode.HALF_UP);
                    BigDecimal singleRealTotalPrice = realTotalPrice.divide(count, 2, RoundingMode.HALF_UP);

                    // 数量为几，就插入几条
                    for (int i = 0; i < count.intValue(); i++) {
                        BaseOrderProject bop = new BaseOrderProject();
                        bop.setOrderId(order.getId());
                        bop.setProjectId(id);
                        bop.setProjectName(name);
                        bop.setProjectQty("1");
                        bop.setUnitPrice(price);
                        bop.setTotalPrice(String.valueOf(singleTotalPriceDecimal));
                        bop.setPreferAmount(String.valueOf(singleDiscountAmountDecimal));
                        bop.setGiveFlag(free);
                        bop.setPic(pic);
                        bop.setStoreId(storeId);
                        bop.setProjectJsonStr(JSON.toJSONString(pm));
                        if (xiaoshouStaff != null) {
                            // 员工提成
                            bop.setCommissionOwner(staffId);
                            bop.setCommissionOwnerName(xiaoshouStaff.getName());
                            BigDecimal rewardRate;
                            BaseStaffStatusSpecial bsss = baseStaffStatusSpecialService.getOne(new QueryWrapper<BaseStaffStatusSpecial>()
                                    .eq("staff_status_id", xiaoshouStaff.getEmployeeId())
                                    .eq("type", "2")
                                    .eq("shop_id", id));
                            if (bsss != null) {
                                rewardRate = new BigDecimal(String.valueOf(bsss.getRewardRate()));
                            } else {
                                BaseStaffStatus bss = baseStaffStatusService.getById(xiaoshouStaff.getEmployeeId());
                                rewardRate = new BigDecimal(String.valueOf(bss.getProjectReward()));
                            }
                            BigDecimal commissionMoney = singleRealTotalPrice.multiply(rewardRate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                            bop.setCommissionMoney(commissionMoney.doubleValue());
                            commissionMoneyAll = commissionMoneyAll.add(commissionMoney);

                            // 销售提成
                            BigDecimal sellMoney = new BigDecimal(String.valueOf(xiaoshouStaff.getSellMoney()));
                            xiaoshouStaff.setSellMoney(sellMoney.add(commissionMoney).doubleValue());
                            // 累计提成
                            BigDecimal totalDeduction = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalDeduction()));
                            xiaoshouStaff.setTotalDeduction(totalDeduction.add(commissionMoney).doubleValue());
                            // 总业绩
                            BigDecimal totalSall = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSell()));
                            xiaoshouStaff.setTotalSell(totalSall.add(singleRealTotalPrice).doubleValue());
                            // 总薪资
                            BigDecimal totalSalary = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSalary()));
                            xiaoshouStaff.setTotalSalary(totalSalary.add(commissionMoney).doubleValue());
                            staffManagementService.updateById(xiaoshouStaff);
                            m.put("staffId", xiaoshouStaff.getId());
                            m.put("staffName", xiaoshouStaff.getName());
                            BigDecimal staffCommission = m.get("staffCommission") == null ? BigDecimal.ZERO : new BigDecimal(String.valueOf(m.get("staffCommission")));
                            m.put("staffCommission", staffCommission.add(commissionMoney));
                        }
                        if (dividendStock != null) {
                            // 股东分红
                            bop.setDividendOwner(dividendStock.getId());
                            bop.setDividendOwnerName(dividendStock.getStockName());

                            // 价格 * 最低利率限额 = 老板最低获利
                            BigDecimal commodityMinimumMargin = new BigDecimal(String.valueOf(pm.getMinimumProfit()));
                            BigDecimal lowPrice = singleTotalPriceDecimal.multiply(commodityMinimumMargin).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                            // 实际售价 * 毛利率 * 股东分红比例 = 股东分红
                            BigDecimal commodityGrossRate = new BigDecimal(String.valueOf(pm.getGrossProfit()));
                            BigDecimal stockProrateDividends = new BigDecimal(String.valueOf(dividendStock.getProrateDividends()));
                            BigDecimal dividendMoney = singleRealTotalPrice.multiply(commodityGrossRate).multiply(stockProrateDividends).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                            // (实际售价 - 股东分红) 应大于 老板最低获利，否则不给股东分红
                            if (lowPrice.compareTo(singleRealTotalPrice.subtract(dividendMoney)) >= 0) {
                                dividendMoney = BigDecimal.ZERO;
                            }
                            bop.setDividendMoney(dividendMoney.doubleValue());
                            dividendMoneyAll = dividendMoneyAll.add(dividendMoney);

                            // 总分红
                            BigDecimal totalDividend = new BigDecimal(String.valueOf(dividendStock.getTotalDividend()));
                            dividendStock.setTotalDividend(totalDividend.add(dividendMoney).doubleValue());
                            // 可提现分红
                            BigDecimal canWithdrawal = new BigDecimal(String.valueOf(dividendStock.getCanWithdrawal()));
                            dividendStock.setCanWithdrawal(canWithdrawal.add(dividendMoney).doubleValue());
                            // 带动营业额
                            BigDecimal driveTurnover = new BigDecimal(String.valueOf(dividendStock.getDriveTurnover()));
                            dividendStock.setDriveTurnover(driveTurnover.add(singleRealTotalPrice).doubleValue());
                            driveTurnoverAll = driveTurnoverAll.add(singleRealTotalPrice);
                            stockManageService.updateById(dividendStock);

                            // 会员带动分红
                            BigDecimal shareholderDividends = new BigDecimal(String.valueOf(mm.getShareholderDividends()));
                            mm.setShareholderDividends(shareholderDividends.add(dividendMoney).doubleValue());
                            memberManagementService.updateById(mm);
                        }
                        bop.setIsValid("1");
                        baseOrderProjectService.save(bop);

                        // 项目关联的商品：一个商品一条记录
                        List<Map<String, Object>> shopList = cashierService.listProjectShop(id);
                        shopList.forEach(map1 -> {
                            if (map1 == null) {
                                return;
                            }
                            String countCommodityStr = map1.get("count") == null ? "0" : String.valueOf(map1.get("count"));
                            BigDecimal countCommodity = new BigDecimal(countCommodityStr);
                            String tradeName = map1.get("trade_name") == null ? null : String.valueOf(map1.get("trade_name"));

                            BaseOrderCommodityWriteoff bocw = new BaseOrderCommodityWriteoff();
                            bocw.setOrderId(order.getId());
                            bocw.setOrderProjectId(bop.getId());
                            bocw.setCommodityName(tradeName);
                            bocw.setTotalQty(countCommodity.intValue());
                            bocw.setRemainQty(countCommodity.intValue());
                            bocw.setWriteoffQty(0);
                            bocw.setStatus(0);
                            bocw.setStoreId(storeId);
                            baseOrderCommodityWriteoffService.save(bocw);
                        });

                        // 项目关联的服务：有多少次服务，就插入多少条记录
                        List<Map<String, Object>> serveList = cashierService.listProjectServe(id);
                        serveList.forEach(map1 -> {
                            if (map1 == null) {
                                return;
                            }
                            String countServeStr = map1.get("count") == null ? "0" : String.valueOf(map1.get("count"));
                            BigDecimal countServe = new BigDecimal(countServeStr);
                            String serveName = map1.get("serve_name") == null ? null : String.valueOf(map1.get("serve_name"));

                            BaseOrderServiceWriteoff bosw = new BaseOrderServiceWriteoff();
                            bosw.setOrderId(order.getId());
                            bosw.setOrderProjectId(bop.getId());
                            bosw.setServiceName(serveName);
                            bosw.setStatus(0);
                            bosw.setStoreId(storeId);
//                  // 服务次数 = 项目数量 * 项目包含服务次数
//                  int i = countServe.multiply(count).intValue();
                            for (int j = 0; j < countServe.intValue(); j++) {
                                baseOrderServiceWriteoffService.save(bosw);
                                bosw.setId(null);
                            }
                        });
                    }
                }
            }
            order.setCommodityListJsonStr(JSON.toJSONString(commodityList));
            order.setCouponListJsonStr(JSON.toJSONString(couponList));

            BigDecimal staffShareMoney = BigDecimal.ZERO;

            // 股东管家分红
            if (StringUtils.isNotEmpty(mm.getMyStockId())) {
                // 消费者是股东
                StockManage stockMe = stockManageService.getById(mm.getMyStockId());
                if (stockMe != null) {
                    // 查出拿分红的员工

                    StaffManagement dividendStaff = staffManagementService.getById(stockMe.getShareholdersHousekeeperId());
                    if (dividendStaff != null) {
                        BigDecimal ratio = new BigDecimal(String.valueOf(stockMe.getShareholdersRatio()));
                        staffShareMoney = realAmountDecimal.multiply(ratio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                        // 分红
                        BigDecimal totalShare = new BigDecimal(String.valueOf(dividendStaff.getTotalShare()));
                        dividendStaff.setTotalShare(totalShare.add(staffShareMoney).doubleValue());
                        // 总薪资
                        BigDecimal totalSalary = new BigDecimal(String.valueOf(dividendStaff.getTotalSalary()));
                        dividendStaff.setTotalSalary(totalSalary.add(staffShareMoney).doubleValue());
                        staffManagementService.updateById(dividendStaff);
                        order.setStaffShareId(dividendStaff.getId());
                        order.setStaffShareName(dividendStaff.getName());
                        order.setStaffShareType("股东");
                    }
                    giveHighStock(mm.getStoreId(), mm.getStockId(), realAmountDecimal);

                }
            } else {
                // 消费者不是股东
                StockManage stockUp = stockManageService.getById(mm.getStockId());
                if (stockUp != null) {
                    // 查出拿分红的员工
                    StaffManagement dividendStaff = staffManagementService.getById(stockUp.getShareholdersHousekeeperId());
                    if (dividendStaff != null) {
                        BigDecimal ratio = new BigDecimal(String.valueOf(stockUp.getMemberRatio()));
                        staffShareMoney = realAmountDecimal.multiply(ratio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                        // 分红
                        BigDecimal totalShare = new BigDecimal(String.valueOf(dividendStaff.getTotalShare()));
                        dividendStaff.setTotalShare(totalShare.add(staffShareMoney).doubleValue());
                        // 总薪资
                        BigDecimal totalSalary = new BigDecimal(String.valueOf(dividendStaff.getTotalSalary()));
                        dividendStaff.setTotalSalary(totalSalary.add(staffShareMoney).doubleValue());
                        staffManagementService.updateById(dividendStaff);
                        order.setStaffShareId(dividendStaff.getId());
                        order.setStaffShareName(dividendStaff.getName());
                        order.setStaffShareType("会员");
                    }
                }
            }
            order.setStaffPercentage(commissionMoneyAll.doubleValue());
            order.setStockPercentage(dividendMoneyAll.doubleValue());
            order.setDriveTurnoverAll(driveTurnoverAll.doubleValue());
            order.setStaffShareMoney(staffShareMoney.doubleValue());
            order.setOrderStatus("1");
            baseOrderService.updateById(order);
            if (orderHasCommodity) {
                // 线上订单生成自提订单
                BaseSelfOrder bso = new BaseSelfOrder();
                BeanUtils.copyProperties(order, bso);
                bso.setId(null);
                bso.setCreateBy(null);
                bso.setCreateTime(null);
                bso.setUpdateBy(null);
                bso.setUpdateTime(null);
                bso.setOrderType("03");
                bso.setStatus("0");
                baseSelfOrderService.save(bso);
                for (BaseSelfOrderCommodity bsoc : bsocList) {
                    bsoc.setOrderId(bso.getId());
                    baseSelfOrderCommodityService.save(bsoc);
                }
            }

            // 会员消费次数
            mm.setConsumption(mm.getConsumption() + 1);
            // 会员消费总额
            BigDecimal expendamount = new BigDecimal(String.valueOf(mm.getExpendamount()));
            mm.setExpendamount(expendamount.add(realAmountDecimal).doubleValue());
            if ("1".equals(mm.getStatus())) {
                // 股东会员消费总额
                BigDecimal stockMemberExpendamount = new BigDecimal(String.valueOf(mm.getStockMemberExpendamount()));
                mm.setStockMemberExpendamount(stockMemberExpendamount.add(realAmountDecimal).doubleValue());
            }
            memberManagementService.updateById(mm);

            // 模板消息
            try {
                String gzhOpenId = mm.getGzhOpenId();
                String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
                if (gzhOpenId == null) {
                    log.info("发送消费提醒模板推送失败，会员未绑定公众号");
                } else {
                    StoreInfo store = storeInfoService.getById(storeId);
                    if (store == null) {
                        log.info("发送消费提醒模板推送失败，未查到店铺信息");
                    } else {
                        String gzhAppId = store.getGzhAppId();
                        String gzhAppSecret = store.getGzhAppSecret();
                        if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                            log.info("发送消费提醒模板推送失败，店铺未绑定公众号");
                        } else {
                            String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                            String result1 = HttpUtils.sendGet(url1);
                            System.out.println("请求token的url:" + url1);
                            JSONObject resultJson1 = JSON.parseObject(result1);
                            String errcode = resultJson1.getString("errcode");
                            if (errcode != null && !"0".equals(errcode)) {
                                log.info("发送消费提醒模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                            } else {
                                String accessToken = resultJson1.getString("access_token");
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                MsgTemplate msgTemplate = msgTemplateListService.getByTitle("消费提醒", storeId);
                                String templateId = msgTemplate.getTemplateId();
                                BaseOrder baseOrder = baseOrderService.getById(order.getId());
                                Integer consumeNoticeFlag = 0;
                                if (baseOrder != null) {
                                    consumeNoticeFlag = baseOrder.getConsumeNoticeFlag();
                                }
                                if (consumeNoticeFlag != 1) {
                                    util.consumeNotice(templateId, gzhOpenId, sdf.format(new Date()), String.valueOf(order.getRealAmount()), order.getStoreName(), store.getXcxAppId(), "user/order/index?type=0", accessToken);
                                    baseOrderService.updateConsumeNoticeFlag(1, order.getId());
                                    log.info("发送消费提醒模板推送成功");
                                }

                            }
                        }
                    }
                }
            } catch (Exception e) {
                log.error("发送消费提醒模板推送失败，发生异常", e);
            }

            if (dividendStock != null && dividendMoneyAll.compareTo(BigDecimal.ZERO) > 0) {
                // 模板消息
                try {
                    MemberManagement mm1 = memberManagementService.getById(dividendStock.getMemberId());
                    String gzhOpenId = mm1.getGzhOpenId();
                    if (gzhOpenId == null) {
                        log.info("发送分红提醒模板推送失败，会员未绑定公众号");
                    } else {
                        StoreInfo store = storeInfoService.getById(storeId);
                        if (store == null) {
                            log.info("发送分红提醒模板推送失败，未查到店铺信息");
                        } else {
                            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
                            String gzhAppId = store.getGzhAppId();
                            String gzhAppSecret = store.getGzhAppSecret();
                            if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                log.info("发送分红提醒模板推送失败，店铺未绑定公众号");
                            } else {
                                String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                String result1 = HttpUtils.sendGet(url1);
                                JSONObject resultJson1 = JSON.parseObject(result1);
                                String errcode = resultJson1.getString("errcode");
                                if (errcode != null && !"0".equals(errcode)) {
                                    log.info("发送分红提醒模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                } else {
                                    String accessToken = resultJson1.getString("access_token");
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                    MsgTemplate msgTemplate = msgTemplateListService.getByTitle("订单分红提醒", storeId);
                                    String templateId = msgTemplate.getTemplateId();
                                    util.orderDividendNotice(templateId, gzhOpenId, String.valueOf(dividendMoneyAll), String.valueOf(dividendStock.getTotalDividend()), sdf.format(new Date()), store.getXcxAppId(), "user/share/bonus", accessToken);

                                    log.info("发送分红提醒模板推送成功");
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("发送分红提醒模板推送失败，发生异常", e);
                }
            }
        }


        return Result.OK(order.getId());
    }


    /**
     * 退单
     * 参数：*orderId
     */
    @ApiOperation(value = "退单", notes = "退单")
    @PostMapping("/returnOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> returnOrder(@RequestBody Map<String, Object> map1) {

        String storeId = map1.get("storeId") == null ? null : String.valueOf(map1.get("storeId"));
        String orderId = map1.get("orderId") == null ? null : String.valueOf(map1.get("orderId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(orderId)) {
            return Result.error("参数不全");
        }

        BaseOrder order = baseOrderService.getById(orderId);
        if (order == null) {
            return Result.error("未找到对应的订单");
        }

        // 退单条件判断
        if (!"1".equals(order.getOrderStatus())) {
            return Result.error("订单未在已付款状态，无法退单");
        }
        List<BaseOrderCommodityWriteoff> bocwList = baseOrderCommodityWriteoffService.list(new QueryWrapper<BaseOrderCommodityWriteoff>().eq("order_id", orderId));
        List<BaseOrderServiceWriteoff> boswList = baseOrderServiceWriteoffService.list(new QueryWrapper<BaseOrderServiceWriteoff>().eq("order_id", orderId));
        long countUsedBocw = bocwList.stream().filter(bocw -> bocw.getWriteoffQty() > 0).count();
        long countUsedBosw = boswList.stream().filter(bosw -> bosw.getStatus() == 1).count();
        if (countUsedBocw > 0 || countUsedBosw > 0) {
            return Result.error("订单中商品或服务已进行过核销，无法退单");
        }

        // 退单逻辑
        Map<String, Object> map = (Map<String, Object>) JSON.parse(order.getOrderJsonStr());
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String payType = map.get("payType") == null ? null : String.valueOf(map.get("payType"));
        String totalAmount = map.get("totalAmount") == null ? null : String.valueOf(map.get("totalAmount"));
        String totalDiscountAmount = map.get("totalDiscountAmount") == null ? null : String.valueOf(map.get("totalDiscountAmount"));
        String realAmount = map.get("realAmount") == null ? null : String.valueOf(map.get("realAmount"));
        List<Map<String, Object>> commodityList = (List<Map<String, Object>>) map.get("commodityList");
        String useMemberDiscountStr = map.get("useMemberDiscount") == null ? null : String.valueOf(map.get("useMemberDiscount"));
        String memberDiscountStr = map.get("memberDiscount") == null ? null : String.valueOf(map.get("memberDiscount"));
        List<Map<String, Object>> couponList = map.get("couponList") == null ? new ArrayList<>() : (List<Map<String, Object>>) map.get("couponList");
        String remark = map.get("remark") == null ? null : String.valueOf(map.get("remark"));
        String preOrderId = map.get("preOrderId") == null ? null : String.valueOf(map.get("preOrderId"));
        BigDecimal realAmountDecimal = new BigDecimal(realAmount);
        String balanceAmountStr = map.get("balanceAmount") == null ? "0" : String.valueOf(map.get("balanceAmount"));
        BigDecimal balanceAmount = new BigDecimal(balanceAmountStr);
        String stockBalanceAmountStr = map.get("stockBalanceAmount") == null ? "0" : String.valueOf(map.get("stockBalanceAmount"));
        BigDecimal stockBalanceAmount = new BigDecimal(stockBalanceAmountStr);
        boolean useMemberDiscount = "1".equals(useMemberDiscountStr);
        BigDecimal memberDiscount = memberDiscountStr == null ? BigDecimal.TEN : new BigDecimal(memberDiscountStr);
        String reductionStr = map.get("reduction") == null ? "0" : String.valueOf(map.get("reduction"));
        BigDecimal reduction = new BigDecimal(reductionStr);
        String outTradeNo = map.get("outTradeNo") == null ? null : String.valueOf(map.get("outTradeNo"));

        MemberManagement mm = memberManagementService.getById(memberId);

        // 参与分红的股东
        StockManage dividendStock = null;

        if ("1".equals(mm.getStatus())) {
            dividendStock = stockManageService.getById(mm.getStockId());
            if (dividendStock != null) {
                MemberManagement dividendStockMember = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("my_stock_id", dividendStock.getId()));
            }
        }
        switch (payType) {
            case "微信支付":
                break;
            case "扫码支付":
            case "现金支付":
            case "支付宝记账":
            case "微信记账":
                if (balanceAmount.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal balance = new BigDecimal(String.valueOf(mm.getBalance()));
                    mm.setBalance(balance.add(balanceAmount).doubleValue());
                    memberManagementService.updateById(mm);
                }
                if (stockBalanceAmount.compareTo(BigDecimal.ZERO) > 0) {
                    StockManage sm = stockManageService.getById(mm.getMyStockId());
                    BigDecimal equityBalance = new BigDecimal(String.valueOf(sm.getEquityBalance()));
                    sm.setEquityBalance(equityBalance.add(stockBalanceAmount).doubleValue());
                    stockManageService.updateById(sm);
                }
                break;
            case "会员余额支付":
                BigDecimal balance = new BigDecimal(String.valueOf(mm.getBalance()));
                mm.setBalance(balance.add(realAmountDecimal).doubleValue());
                memberManagementService.updateById(mm);
                break;
            case "股本余额支付":
                StockManage sm = stockManageService.getById(mm.getMyStockId());
                BigDecimal equityBalance = new BigDecimal(String.valueOf(sm.getEquityBalance()));
                sm.setEquityBalance(equityBalance.add(realAmountDecimal).doubleValue());
                stockManageService.updateById(sm);
                break;
        }

        for (Map<String, Object> m : couponList) {
            String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
            String numStr = m.get("num") == null ? "0" : String.valueOf(m.get("num"));
            int num = Integer.parseInt(numStr);
            BaseMemberVipCoupon bmvc = baseMemberVipCouponService.getById(id);
            bmvc.setNum(bmvc.getNum() + num);
            baseMemberVipCouponService.updateById(bmvc);

        }
        // 订单总员工销售提成
        BigDecimal commissionMoneyAll = BigDecimal.ZERO;
        // 订单总股东分红
        BigDecimal dividendMoneyAll = BigDecimal.ZERO;
        // 订单总带动营业额
        BigDecimal driveTurnoverAll = BigDecimal.ZERO;

//      // 出库记录明细
//      List<OutStorageDetail> outStorageDetailList = new ArrayList<>();
        // 入库记录明细
        List<InStorageDetail> inStorageDetailList = new ArrayList<>();
        // 出入库明细
        List<StorageOutinDetail> storageOutinDetailList = new ArrayList<>();

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        for (Map<String, Object> m : commodityList) {
            String id = m.get("id") == null ? null : String.valueOf(m.get("id"));
            String type = m.get("type") == null ? null : String.valueOf(m.get("type"));
            String countStr = m.get("count") == null ? "0" : String.valueOf(m.get("count"));
            BigDecimal count = new BigDecimal(countStr);
            String name = m.get("name") == null ? "0" : String.valueOf(m.get("name"));
            String specification = m.get("specification") == null ? "0" : String.valueOf(m.get("specification"));
            String price = m.get("price") == null ? "0" : String.valueOf(m.get("price"));
            String totalPrice = m.get("totalPrice") == null ? "0" : String.valueOf(m.get("totalPrice"));
            String discountAmount = m.get("discountAmount") == null ? "0" : String.valueOf(m.get("discountAmount"));
            String free = m.get("free") == null ? "0" : String.valueOf(m.get("free"));
            String pic = m.get("pic") == null ? "0" : String.valueOf(m.get("pic"));
            String staffId = m.get("staffId") == null ? "0" : String.valueOf(m.get("staffId"));

            BigDecimal totalPriceDecimal = new BigDecimal(totalPrice);
            BigDecimal discountAmountDecimal = new BigDecimal(discountAmount);
            BigDecimal realTotalPrice = totalPriceDecimal.subtract(discountAmountDecimal);

            // 拿销售提成的员工
            StaffManagement xiaoshouStaff = staffManagementService.getById(staffId);

            if ("1".equals(type)) {
                // ------------------------- 商品 -------------------------

                CommodityManagement cm = commodityManagementService.getById(id);
                if (cm != null) {
                    cm.setInventory(cm.getInventory() + count.intValue());
                    commodityManagementService.updateById(cm);

                    // 入库记录明细
                    InStorageDetail inStorageDetail = new InStorageDetail();
                    inStorageDetail.setCommodityId(id);
                    inStorageDetail.setCommodityName(cm.getTradeName());
                    inStorageDetail.setCommoditySpecs(cm.getSpecification());
                    inStorageDetail.setInQty(count.intValue());
                    inStorageDetail.setStoreId(storeId);
                    inStorageDetailList.add(inStorageDetail);

                    // 出入库明细
                    StorageOutinDetail storageOutinDetail = new StorageOutinDetail();
                    storageOutinDetail.setCommodityName(cm.getTradeName());
                    storageOutinDetail.setCommodityId(cm.getId());
                    storageOutinDetail.setOperateType("入库操作");
                    storageOutinDetail.setOutinQty(count.intValue());
                    storageOutinDetail.setRemainQty(cm.getInventory());
                    storageOutinDetail.setBillTime(new Date());
                    storageOutinDetail.setOperator(sysUser.getRealname());
                    storageOutinDetail.setStoreId(storeId);
                    storageOutinDetailList.add(storageOutinDetail);
                }

                BaseOrderCommodity boc = new BaseOrderCommodity();
                boc.setOrderId(order.getId());
                boc.setCommodityId(id);
                boc.setCommodityName(name);
                boc.setCommoditySpecs(specification);
                boc.setCommodityQty(countStr);
                boc.setUnitPrice(price);
                boc.setTotalPrice(totalPrice);
                boc.setPreferAmount(discountAmount);
                boc.setGiveFlag(free);
                boc.setPic(pic);
                boc.setStoreId(storeId);
                boc.setCommodityJsonStr(JSON.toJSONString(cm));
                if (xiaoshouStaff != null) {
                    // 员工提成
                    boc.setCommissionOwner(staffId);
                    boc.setCommissionOwnerName(xiaoshouStaff.getName());
                    BigDecimal rewardRate;
                    BaseStaffStatusSpecial bsss = baseStaffStatusSpecialService.getOne(new QueryWrapper<BaseStaffStatusSpecial>()
                            .eq("staff_status_id", xiaoshouStaff.getEmployeeId())
                            .eq("type", "1")
                            .eq("shop_id", id));
                    if (bsss != null) {
                        rewardRate = new BigDecimal(String.valueOf(bsss.getRewardRate()));
                    } else {
                        BaseStaffStatus bss = baseStaffStatusService.getById(xiaoshouStaff.getEmployeeId());
                        rewardRate = new BigDecimal(String.valueOf(bss.getShopReward()));
                    }
                    BigDecimal commissionMoney = realTotalPrice.multiply(rewardRate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    boc.setCommissionMoney(commissionMoney.doubleValue());
                    commissionMoneyAll = commissionMoneyAll.add(commissionMoney);

                    // 销售提成
                    BigDecimal sellMoney = new BigDecimal(String.valueOf(xiaoshouStaff.getSellMoney()));
                    xiaoshouStaff.setSellMoney(sellMoney.subtract(commissionMoney).doubleValue());
                    // 累计提成
                    BigDecimal totalDeduction = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalDeduction()));
                    xiaoshouStaff.setTotalDeduction(totalDeduction.subtract(commissionMoney).doubleValue());
                    // 总业绩
                    BigDecimal totalSall = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSell()));
                    xiaoshouStaff.setTotalSell(totalSall.subtract(realTotalPrice).doubleValue());
                    // 总薪资
                    BigDecimal totalSalary = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSalary()));
                    xiaoshouStaff.setTotalSalary(totalSalary.subtract(commissionMoney).doubleValue());
                    staffManagementService.updateById(xiaoshouStaff);
                    m.put("staffId", xiaoshouStaff.getId());
                    m.put("staffName", xiaoshouStaff.getName());
                    m.put("staffCommission", commissionMoney);
                }
                if (dividendStock != null) {
                    // 股东分红
                    boc.setDividendOwner(dividendStock.getId());
                    boc.setDividendOwnerName(dividendStock.getStockName());

                    // 价格 * 最低利率限额 = 老板最低获利
                    BigDecimal commodityMinimumMargin = new BigDecimal(String.valueOf(cm.getMinimumMargin()));
                    BigDecimal lowPrice = totalPriceDecimal.multiply(commodityMinimumMargin).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    // 实际售价 * 毛利率 * 股东分红比例 = 股东分红
                    BigDecimal commodityGrossRate = new BigDecimal(String.valueOf(cm.getGrossRate()));
                    BigDecimal stockProrateDividends = new BigDecimal(String.valueOf(dividendStock.getProrateDividends()));
                    BigDecimal dividendMoney = realTotalPrice.multiply(commodityGrossRate).multiply(stockProrateDividends).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                    // (实际售价 - 股东分红) 应大于 老板最低获利，否则不给股东分红
                    if (lowPrice.compareTo(realTotalPrice.subtract(dividendMoney)) >= 0) {
                        dividendMoney = BigDecimal.ZERO;
                    }
                    boc.setDividendMoney(dividendMoney.doubleValue());
                    dividendMoneyAll = dividendMoneyAll.add(dividendMoney);

                    // 总分红
                    BigDecimal totalDividend = new BigDecimal(String.valueOf(dividendStock.getTotalDividend()));
                    dividendStock.setTotalDividend(totalDividend.subtract(dividendMoney).doubleValue());
                    // 可提现分红
                    BigDecimal canWithdrawal = new BigDecimal(String.valueOf(dividendStock.getCanWithdrawal()));
                    dividendStock.setCanWithdrawal(canWithdrawal.subtract(dividendMoney).doubleValue());
                    // 带动营业额
                    BigDecimal driveTurnover = new BigDecimal(String.valueOf(dividendStock.getDriveTurnover()));
                    dividendStock.setDriveTurnover(driveTurnover.subtract(realTotalPrice).doubleValue());
                    driveTurnoverAll = driveTurnoverAll.add(realTotalPrice);
                    stockManageService.updateById(dividendStock);

                    // 会员带动分红
                    BigDecimal shareholderDividends = new BigDecimal(String.valueOf(mm.getShareholderDividends()));
                    mm.setShareholderDividends(shareholderDividends.subtract(dividendMoney).doubleValue());
                    memberManagementService.updateById(mm);
                }
            } else {
                // ------------------------- 项目 -------------------------
                ProjectManagement pm = projectManagementService.getById(id);

                BaseOrderProject bop = new BaseOrderProject();
                bop.setOrderId(order.getId());
                bop.setProjectId(id);
                bop.setProjectName(name);
                bop.setProjectQty(countStr);
                bop.setUnitPrice(price);
                bop.setTotalPrice(totalPrice);
                bop.setPreferAmount(discountAmount);
                bop.setGiveFlag(free);
                bop.setPic(pic);
                bop.setStoreId(storeId);
                bop.setProjectJsonStr(JSON.toJSONString(pm));
                if (xiaoshouStaff != null) {
                    // 员工提成
                    bop.setCommissionOwner(staffId);
                    bop.setCommissionOwnerName(xiaoshouStaff.getName());
                    BigDecimal rewardRate;
                    BaseStaffStatusSpecial bsss = baseStaffStatusSpecialService.getOne(new QueryWrapper<BaseStaffStatusSpecial>()
                            .eq("staff_status_id", xiaoshouStaff.getEmployeeId())
                            .eq("type", "2")
                            .eq("shop_id", id));
                    if (bsss != null) {
                        rewardRate = new BigDecimal(String.valueOf(bsss.getRewardRate()));
                    } else {
                        BaseStaffStatus bss = baseStaffStatusService.getById(xiaoshouStaff.getEmployeeId());
                        rewardRate = new BigDecimal(String.valueOf(bss.getProjectReward()));
                    }
                    BigDecimal commissionMoney = realTotalPrice.multiply(rewardRate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    bop.setCommissionMoney(commissionMoney.doubleValue());
                    commissionMoneyAll = commissionMoneyAll.add(commissionMoney);

                    // 销售提成
                    BigDecimal sellMoney = new BigDecimal(String.valueOf(xiaoshouStaff.getSellMoney()));
                    xiaoshouStaff.setSellMoney(sellMoney.subtract(commissionMoney).doubleValue());
                    // 累计提成
                    BigDecimal totalDeduction = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalDeduction()));
                    xiaoshouStaff.setTotalDeduction(totalDeduction.subtract(commissionMoney).doubleValue());
                    // 总业绩
                    BigDecimal totalSall = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSell()));
                    xiaoshouStaff.setTotalSell(totalSall.subtract(realTotalPrice).doubleValue());
                    // 总薪资
                    BigDecimal totalSalary = new BigDecimal(String.valueOf(xiaoshouStaff.getTotalSalary()));
                    xiaoshouStaff.setTotalSalary(totalSalary.subtract(commissionMoney).doubleValue());
                    staffManagementService.updateById(xiaoshouStaff);
                    m.put("staffId", xiaoshouStaff.getId());
                    m.put("staffName", xiaoshouStaff.getName());
                    m.put("staffCommission", commissionMoney);
                }
                if (dividendStock != null) {
                    // 股东分红
                    bop.setDividendOwner(dividendStock.getId());
                    bop.setDividendOwnerName(dividendStock.getStockName());

                    // 价格 * 最低利率限额 = 老板最低获利
                    BigDecimal commodityMinimumMargin = new BigDecimal(String.valueOf(pm.getMinimumProfit()));
                    BigDecimal lowPrice = totalPriceDecimal.multiply(commodityMinimumMargin).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    // 实际售价 * 毛利率 * 股东分红比例 = 股东分红
                    BigDecimal commodityGrossRate = new BigDecimal(String.valueOf(pm.getGrossProfit()));
                    BigDecimal stockProrateDividends = new BigDecimal(String.valueOf(dividendStock.getProrateDividends()));
                    BigDecimal dividendMoney = realTotalPrice.multiply(commodityGrossRate).multiply(stockProrateDividends).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                    // (实际售价 - 股东分红) 应大于 老板最低获利，否则不给股东分红
                    if (lowPrice.compareTo(realTotalPrice.subtract(dividendMoney)) >= 0) {
                        dividendMoney = BigDecimal.ZERO;
                    }
                    bop.setDividendMoney(dividendMoney.doubleValue());
                    dividendMoneyAll = dividendMoneyAll.add(dividendMoney);

                    // 总分红
                    BigDecimal totalDividend = new BigDecimal(String.valueOf(dividendStock.getTotalDividend()));
                    dividendStock.setTotalDividend(totalDividend.subtract(dividendMoney).doubleValue());
                    // 可提现分红
                    BigDecimal canWithdrawal = new BigDecimal(String.valueOf(dividendStock.getCanWithdrawal()));
                    dividendStock.setCanWithdrawal(canWithdrawal.subtract(dividendMoney).doubleValue());
                    // 带动营业额
                    BigDecimal driveTurnover = new BigDecimal(String.valueOf(dividendStock.getDriveTurnover()));
                    dividendStock.setDriveTurnover(driveTurnover.subtract(realTotalPrice).doubleValue());
                    driveTurnoverAll = driveTurnoverAll.add(realTotalPrice);
                    stockManageService.updateById(dividendStock);

                    // 会员带动分红
                    BigDecimal shareholderDividends = new BigDecimal(String.valueOf(mm.getShareholderDividends()));
                    mm.setShareholderDividends(shareholderDividends.subtract(dividendMoney).doubleValue());
                    memberManagementService.updateById(mm);
                }
                bop.setIsValid("1");
                baseOrderProjectService.save(bop);

            }
        }

        BigDecimal staffShareMoney = BigDecimal.ZERO;

        // 股东管家分红
        if (StringUtils.isNotEmpty(mm.getMyStockId())) {
            // 消费者是股东
            StockManage stockMe = stockManageService.getById(mm.getMyStockId());
            if (stockMe != null) {
                // 查出拿分红的员工
                StaffManagement dividendStaff = staffManagementService.getById(stockMe.getShareholdersHousekeeperId());
                if (dividendStaff != null) {
                    BigDecimal ratio = new BigDecimal(String.valueOf(stockMe.getShareholdersRatio()));
                    staffShareMoney = realAmountDecimal.multiply(ratio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    // 分红
                    BigDecimal totalShare = new BigDecimal(String.valueOf(dividendStaff.getTotalShare()));
                    dividendStaff.setTotalShare(totalShare.subtract(staffShareMoney).doubleValue());
                    // 总薪资
                    BigDecimal totalSalary = new BigDecimal(String.valueOf(dividendStaff.getTotalSalary()));
                    dividendStaff.setTotalSalary(totalSalary.subtract(staffShareMoney).doubleValue());
                    staffManagementService.updateById(dividendStaff);
                }
            }
        } else {
            // 消费者不是股东
            StockManage stockUp = stockManageService.getById(mm.getStockId());
            if (stockUp != null) {
                // 查出拿分红的员工
                StaffManagement dividendStaff = staffManagementService.getById(stockUp.getShareholdersHousekeeperId());
                if (dividendStaff != null) {
                    BigDecimal ratio = new BigDecimal(String.valueOf(stockUp.getMemberRatio()));
                    staffShareMoney = realAmountDecimal.multiply(ratio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    // 分红
                    BigDecimal totalShare = new BigDecimal(String.valueOf(dividendStaff.getTotalShare()));
                    dividendStaff.setTotalShare(totalShare.subtract(staffShareMoney).doubleValue());
                    // 总薪资
                    BigDecimal totalSalary = new BigDecimal(String.valueOf(dividendStaff.getTotalSalary()));
                    dividendStaff.setTotalSalary(totalSalary.subtract(staffShareMoney).doubleValue());
                    staffManagementService.updateById(dividendStaff);
                }
            }
        }

        // 更新订单
        order.setOrderStatus("2");
        baseOrderService.updateById(order);

        // 两个待核销删掉
        baseOrderServiceWriteoffService.remove(new QueryWrapper<BaseOrderServiceWriteoff>().eq("order_id", orderId));
        baseOrderCommodityWriteoffService.remove(new QueryWrapper<BaseOrderCommodityWriteoff>().eq("order_id", orderId));

        BaseSelfOrder baseSelfOrder = baseSelfOrderService.getOne(new QueryWrapper<BaseSelfOrder>().eq("order_code", order.getOrderCode()));
        if (baseSelfOrder != null) {
            baseSelfOrder.setOrderStatus("2");
            baseSelfOrderService.updateById(baseSelfOrder);
        }

        // 不处理
//      // 会员消费次数
//      mm.setConsumption(mm.getConsumption() + 1);
        // 会员消费总额
        BigDecimal expendamount = new BigDecimal(String.valueOf(mm.getExpendamount()));
        mm.setExpendamount(expendamount.subtract(realAmountDecimal).doubleValue());
        if ("1".equals(mm.getStatus())) {
            // 股东会员消费总额
            BigDecimal stockMemberExpendamount = new BigDecimal(String.valueOf(mm.getStockMemberExpendamount()));
            mm.setStockMemberExpendamount(stockMemberExpendamount.subtract(realAmountDecimal).doubleValue());
        }
        memberManagementService.updateById(mm);

        // 模板消息
        try {
            String gzhOpenId = mm.getGzhOpenId();
            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
            if (gzhOpenId == null) {
                log.info("发送退款通知模板推送失败，会员未绑定公众号");
            } else {
                StoreInfo store = storeInfoService.getById(storeId);
                if (store == null) {
                    log.info("发送退款通知模板推送失败，未查到店铺信息");
                } else {
                    String gzhAppId = store.getGzhAppId();
                    String gzhAppSecret = store.getGzhAppSecret();
                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                        log.info("发送退款通知模板推送失败，店铺未绑定公众号");
                    } else {
                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                        String result1 = HttpUtils.sendGet(url1);
                        JSONObject resultJson1 = JSON.parseObject(result1);
                        String errcode = resultJson1.getString("errcode");
                        if (errcode != null && !"0".equals(errcode)) {
                            log.info("发送退款通知模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                        } else {
                            String accessToken = resultJson1.getString("access_token");
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("退款通知", storeId);
                            String templateId = msgTemplate.getTemplateId();
                            util.refundNotice(templateId, gzhOpenId, order.getStoreName(), String.valueOf(order.getRealAmount()), order.getOrderCode(), sdf.format(new Date()), store.getXcxAppId(), "user/order/index?type=2", accessToken);

                            log.info("发送退款通知模板推送成功");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("发送退款通知模板推送失败，发生异常", e);
        }

        if (dividendStock != null) {
            // 模板消息
            try {
                MemberManagement mm1 = memberManagementService.getById(dividendStock.getMemberId());
                String gzhOpenId = mm1.getGzhOpenId();
                if (gzhOpenId == null) {
                    log.info("发送股东会员退款通知模板推送失败，会员未绑定公众号");
                } else {
                    StoreInfo store = storeInfoService.getById(storeId);
                    if (store == null) {
                        log.info("发送股东会员退款通知模板推送失败，未查到店铺信息");
                    } else {
                        String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
                        String gzhAppId = store.getGzhAppId();
                        String gzhAppSecret = store.getGzhAppSecret();
                        if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                            log.info("发送股东会员退款通知模板推送失败，店铺未绑定公众号");
                        } else {
                            String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                            String result1 = HttpUtils.sendGet(url1);
                            JSONObject resultJson1 = JSON.parseObject(result1);
                            String errcode = resultJson1.getString("errcode");
                            if (errcode != null && !"0".equals(errcode)) {
                                log.info("发送股东会员退款通知模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                            } else {
                                String accessToken = resultJson1.getString("access_token");
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                MsgTemplate msgTemplate = msgTemplateListService.getByTitle("用户退款通知", storeId);
                                String templateId = msgTemplate.getTemplateId();
                                util.memberRefundNotice(templateId, gzhOpenId, mm.getName(), remark == null ? "" : remark, String.valueOf(order.getRealAmount()), sdf.format(new Date()), store.getXcxAppId(), "user/share/bonus", accessToken);

                                log.info("发送股东会员退款通知模板推送成功");
                            }
                        }
                    }
                }
            } catch (Exception e) {
                log.error("发送股东会员退款通知模板推送失败，发生异常", e);
            }
        }

        return Result.OK("退单成功");
    }

    // --------------------------------------- 我的 ---------------------------------------

    /**
     * 小程序注册
     * （前端使用wx.login获取code，使用code调用后端接口1，后端调用api：auth.code2Session获取openid和unionid）
     * loginType（1.直接进入小程序。2.扫码领卡）
     */
    @ApiOperation(value = "小程序注册", notes = "小程序注册")
    @PostMapping("/xcx/register")
    public Result<?> xcxRegister(@RequestBody Map<String, Object> params) {

        log.info("register, params = {}", params);

        String storeId = params.get("storeId") == null ? null : String.valueOf(params.get("storeId"));
        String code = params.get("code") == null ? null : String.valueOf(params.get("code"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(code)) {
            return Result.error("参数不全");
        }
        String loginType = params.get("loginType") == null ? null : String.valueOf(params.get("loginType"));

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("店铺不存在");
        }
        String xcxAppId = store.getXcxAppId();
        String xcxAppSecret = store.getXcxAppSecret();
        if (StringUtils.isEmpty(xcxAppId) || StringUtils.isEmpty(xcxAppSecret)) {
            return Result.error("店铺还未绑定小程序");
        }

        String xcxOpenId;
        String unionId;
        try {
            String url2 = "https://api.weixin.qq.com/sns/jscode2session?appid=" + xcxAppId + "&secret=" + xcxAppSecret + "&js_code=" + code + "&grant_type=authorization_code";
            String result2 = HttpUtils.sendGet(url2);
            log.debug("微信调用：url = {}, result = {}", url2, result2);
            JSONObject resultJson2 = JSON.parseObject(result2);
            String errcode = resultJson2.getString("errcode");
            if (errcode != null && !"0".equals(errcode)) {
                log.debug("调用微信api返回值异常，错误码：{}", errcode);
                return Result.error("调用微信api发生异常，错误码：" + errcode + "result：" + result2);
            }
            xcxOpenId = resultJson2.getString("openid");
            unionId = resultJson2.getString("unionid");
        } catch (Exception e) {
            log.error("调用微信api发生异常", e);
            return Result.error("调用微信api发生异常");
        }

        Map<String, Object> result = new HashMap<>();

        //MemberManagement mm = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("store_id", storeId).eq("union_id", unionId));
        MemberManagement mm = memberManagementService.getOneRecord(storeId, unionId);
        if (mm == null) {
            MemberManagement mm1 = new MemberManagement();
            mm1.setStoreId(storeId);
            mm1.setXcxOpenId(xcxOpenId);
            mm1.setUnionId(unionId);
            mm1.setUserinfoStatus("0");
            mm1.setConsumption(0);
            mm1.setAmount(0.00);
            mm1.setBalance(0.00);
            mm1.setExpendamount(0.00);
            mm1.setShareholderDividends(0.00);
            mm1.setStockMemberExpendamount(0.00);
            mm1.setRegistrationDate(new Date());
            mm1.setWhetherConcern("0");

            mm1.setIsNew("1");

            mm1.setStatus("2");
            mm1.setMemberType("店铺会员");
            List<LevelSet> levelSetList = levelSetService.list(new QueryWrapper<LevelSet>().eq("store_id", storeId).orderByAsc("rank_num"));
            if (levelSetList == null || levelSetList.size() == 0) {
                return Result.error("注册失败，店铺还未创建会员等级");
            }
            mm1.setLevelId(levelSetList.get(0).getId());
            mm1.setShareholders(null);
            mm1.setBelongStore(null);
            mm1.setMemberLevel(null);
            mm1.setCreateBy("xcx");
            memberManagementService.save(mm1);

            result.put("hasNickName", mm1.getNickName() != null);
            result.put("hasPhone", mm1.getPhone() != null);
            result.put("subscribeTencent", "1".equals(mm1.getWhetherConcern()));
            result.put("member", mm1);
            return Result.OK(result);
        } else {
            mm.setXcxOpenId(xcxOpenId);
            mm.setUpdateBy("xcx");
            memberManagementService.updateById(mm);

            result.put("hasNickName", mm.getNickName() != null);
            result.put("hasPhone", mm.getPhone() != null);
            result.put("subscribeTencent", "1".equals(mm.getWhetherConcern()));
            result.put("member", mm);
            return Result.OK(result);
        }
    }

    /**
     * 小程序获取手机号
     * （前端使用getPhoneNumber获取code，使用code调用后端接口2，后端调用api：phonenumber.getPhoneNumber获取手机号）
     */
    @ApiOperation(value = "小程序获取手机号", notes = "小程序获取手机号")
    @PostMapping("/xcx/getPhone")
    public Result<?> xcxGetPhone(@RequestBody Map<String, Object> params) {

        log.info("getPhone, params = {}", params);

        String storeId = params.get("storeId") == null ? null : String.valueOf(params.get("storeId"));
        String code = params.get("code") == null ? null : String.valueOf(params.get("code"));
        String xcxOpenId = params.get("xcxOpenId") == null ? null : String.valueOf(params.get("xcxOpenId"));
        String unionId = params.get("unionId") == null ? null : String.valueOf(params.get("unionId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(code) || StringUtils.isEmpty(xcxOpenId) || StringUtils.isEmpty(unionId)) {
            log.info("参数不全：storeId=" + storeId + " code=" + code + "xcxOpenId=" + xcxOpenId + "unionId=" + unionId);
            return Result.error("参数不全");
        }

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            log.info("店铺不存在");
            return Result.error("店铺不存在");
        }
        String xcxAppId = store.getXcxAppId();
        String xcxAppSecret = store.getXcxAppSecret();
        if (StringUtils.isEmpty(xcxAppId) || StringUtils.isEmpty(xcxAppSecret)) {
            log.info("店铺还未绑定小程序");
            return Result.error("店铺还未绑定小程序");
        }

        String phone;
        try {
            String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + xcxAppId + "&secret=" + xcxAppSecret;
            String result1 = HttpUtils.sendGet(url1);
            JSONObject resultJson1 = JSON.parseObject(result1);
            String errcode = resultJson1.getString("errcode");
            if (errcode != null && !"0".equals(errcode)) {
                log.debug("获取accessToken返回值异常，错误码：{}", errcode);
                return Result.error("获取accessToken返回值异常，错误码：" + errcode + "result：" + resultJson1);
            }
            String accessToken = resultJson1.getString("access_token");

            String url2 = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
            JSONObject params1 = new JSONObject();
            params1.put("code", code);
            String result2 = HttpUtils.sendPostJson(params1, url2);
            log.debug("微信调用：url = {}, params = {}, result = {}", url2, params1, result2);
            JSONObject resultJson2 = JSON.parseObject(result2);
            String errcode2 = resultJson2.getString("errcode");
            if (errcode2 != null && !"0".equals(errcode2)) {
                log.debug("调用微信api返回值异常，错误码：{}", errcode2);
                return Result.error("调用微信api返回值异常，错误码：" + errcode2 + "result：" + resultJson2);
            }
            JSONObject phoneInfo = resultJson2.getJSONObject("phone_info");
            phone = phoneInfo.getString("purePhoneNumber");
        } catch (Exception e) {
            log.error("调用微信api发生异常", e);
            return Result.error("调用微信api发生异常");
        }

        MemberManagement mm = memberManagementService.getOneRecord(storeId, unionId);
        if (mm == null) {
            log.info("存储手机号失败，unionId未注册");
            return Result.error("存储手机号失败，unionId未注册");
        }

        MemberManagement mm2 = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("store_id", storeId).eq("phone", phone));
        if (mm2 != null) {
            mm2.setNickName(mm.getNickName());
            mm2.setHeadPortrait(mm.getHeadPortrait());
            if (mm2.getSex() == null) {
                mm2.setSex(mm.getSex());
            }
            if (mm2.getName() == null) {
                mm2.setName(mm.getNickName());
            }
            mm2.setUserinfoStatus("1");
            mm2.setXcxOpenId(xcxOpenId);
            mm2.setUnionId(unionId);
            mm2.setUpdateBy("xcx");
            memberManagementService.updateById(mm2);

            List<BaseMemberToReceiveVip> toReceiveVipList = baseMemberToReceiveVipService.list(new QueryWrapper<BaseMemberToReceiveVip>().eq("store_id", storeId).eq("member_id", mm.getId()));
            for (BaseMemberToReceiveVip toReceiveVip : toReceiveVipList) {
                toReceiveVip.setMemberId(mm2.getId());
                toReceiveVip.setUpdateBy("xcx");
                baseMemberToReceiveVipService.updateById(toReceiveVip);
            }
            memberManagementService.removeById(mm.getId());
            return Result.OK(mm2);
        } else {
            mm.setPhone(phone);
            mm.setUserinfoStatus("1");
            mm.setUpdateBy("xcx");
            memberManagementService.updateById(mm);
            return Result.OK(mm);
        }
    }

    /**
     * 小程序更新昵称、头像、性别
     */
    @ApiOperation(value = "小程序更新昵称、头像、性别", notes = "小程序更新昵称、头像、性别")
    @PostMapping("/xcx/updateUserNickName")
    public Result<?> xcxUpdateUserNickName(@RequestBody Map<String, Object> params) {

        log.info("updateUserNickName, params = {}", params);

        String storeId = params.get("storeId") == null ? null : String.valueOf(params.get("storeId"));
        String xcxOpenId = params.get("xcxOpenId") == null ? null : String.valueOf(params.get("xcxOpenId"));
        String unionId = params.get("unionId") == null ? null : String.valueOf(params.get("unionId"));
        String nickName = params.get("nickName") == null ? null : String.valueOf(params.get("nickName"));
        String headPortrait = params.get("headPortrait") == null ? null : String.valueOf(params.get("headPortrait"));
        String sex = params.get("sex") == null ? null : String.valueOf(params.get("sex"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(xcxOpenId) || StringUtils.isEmpty(unionId)
                || StringUtils.isEmpty(nickName) || StringUtils.isEmpty(headPortrait) || StringUtils.isEmpty(sex)) {
            return Result.error("参数不全");
        }

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("店铺不存在");
        }
        String xcxAppId = store.getXcxAppId();
        String xcxAppSecret = store.getXcxAppSecret();
        if (StringUtils.isEmpty(xcxAppId) || StringUtils.isEmpty(xcxAppSecret)) {
            return Result.error("店铺还未绑定小程序");
        }

        MemberManagement mm = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("store_id", storeId).eq("union_id", unionId));
        if (mm == null) {
            return Result.error("存储手机号失败，unionId未注册");
        }

        mm.setNickName(nickName);
        mm.setHeadPortrait(headPortrait);
        if (mm.getSex() == null) {
            if ("男".equals(sex)) {
                mm.setSex("01");
            } else if ("女".equals(sex)) {
                mm.setSex("02");
            } else {
                mm.setSex("03");
            }
        }
        if (mm.getName() == null) {
            mm.setName(nickName);
        }
        mm.setUserinfoStatus("1");
        mm.setUpdateBy("xcx");
        memberManagementService.updateById(mm);

        // 模板消息
        try {
            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
            if (bossGzhOpenId == null) {
                log.info("新增会员通知模板推送失败，老板未绑定公众号");
            } else {
                if (store == null) {
                    log.info("新增会员通知模板推送失败，未查到店铺信息");
                } else {
                    String gzhAppId = store.getGzhAppId();
                    String gzhAppSecret = store.getGzhAppSecret();
                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                        log.info("新增会员通知模板推送失败，店铺未绑定公众号");
                    } else {
                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                        String result1 = HttpUtils.sendGet(url1);
                        JSONObject resultJson1 = JSON.parseObject(result1);
                        String errcode = resultJson1.getString("errcode");
                        if (errcode != null && !"0".equals(errcode)) {
                            log.info("新增会员通知模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                        } else {
                            String accessToken = resultJson1.getString("access_token");
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
//                            if(mm.getStatus() == "2")
//                            {
                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("新增成员提醒", storeId);
                            String templateId = msgTemplate.getTemplateId();
                            //util.addMemberNotice(templateId,bossGzhOpenId,mm.getNickName(), sdf.format(new Date()),store.getStoreName(), store.getXcxAppId(), "", accessToken);
                            //}
                            log.info("新增会员通知模板推送成功");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("新增会员通知模板推送失败，发生异常", e);
        }
        return Result.OK(mm);
    }

    /**
     * 获取我的信息（包含下单所需会员信息）
     */
    @ApiOperation(value = "获取我的信息", notes = "获取我的信息")
    @GetMapping("/getUserInfo")
    public Result<?> getUserInfo(@RequestParam("storeId") String storeId, @RequestParam("xcxOpenId") String xcxOpenId) {

        MemberManagement mm = memberManagementService.getOne(new QueryWrapper<MemberManagement>().eq("store_id", storeId).eq("xcx_open_id", xcxOpenId));
        if (mm == null) {
            return Result.error("会员不存在");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("storeId", storeId);
        map.put("id", mm.getId());
        Map<String, Object> result = cashierService.getMember(map);
        String sex = String.valueOf(result.get("sex"));
        if ("01".equals(sex)) {
            result.put("sexName", "男");
        } else if ("02".equals(sex)) {
            result.put("sexName", "女");
        } else if ("03".equals(sex)) {
            result.put("sexName", "保密");
        }
        // 贵宾卡数量
        int vipCount = baseMemberVipService.count(new QueryWrapper<BaseMemberVip>().eq("store_id", storeId).eq("member_id", mm.getId()));
        result.put("vipCount", vipCount);
        // 股东会员数量
        if (StringUtils.isNotEmpty(mm.getMyStockId())) {
            int stockMemberCount = memberManagementService.count(new QueryWrapper<MemberManagement>().eq("store_id", storeId).eq("stock_id", mm.getMyStockId()));
            result.put("stockMemberCount", stockMemberCount);
        } else {
            result.put("stockMemberCount", 0);
        }
        List<StockManage> list = stockManageService.list(new QueryWrapper<StockManage>().eq("store_id", storeId).eq("member_id", mm.getId()));
        if (list.size() > 0) {
            StockManage stockManage = list.get(0);

            result.put("indirectProrateDividends", stockManage.getIndirectProrateDividends());
        }
        return Result.OK(result);
    }

//    /**
//     * 查询会员信息（会员名称、性别、生日）
//     * 参数：*storeId, *memberId
//     */
//    @PostMapping("/getUserNameInfo")
//    public Result<?> getUserNameInfo(@RequestBody Map<String, Object> map) {
//
//        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
//        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
//        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
//            return Result.error("参数不全");
//        }
//
//        return Result.OK(memberManagementService.getById(memberId));
//    }

    /**
     * 修改会员信息（会员名称、性别、生日）
     * 参数：*storeId, *memberId, name, sex（01.男02.女03.保密）, birthday（yyyy-MM-dd）
     */
    @ApiOperation(value = "修改会员信息", notes = "修改会员信息")
    @PostMapping("/updateUserNameInfo")
    public Result<?> updateUserNameInfo(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }
        String name = map.get("name") == null ? null : String.valueOf(map.get("name"));
        String sex = map.get("sex") == null ? null : String.valueOf(map.get("sex"));
        String birthday = map.get("birthday") == null ? null : String.valueOf(map.get("birthday"));

        MemberManagement mm = new MemberManagement();
        mm.setId(memberId);
        mm.setName(name);
        mm.setSex(sex);
        mm.setBirthday(birthday);
        memberManagementService.updateById(mm);

        return Result.OK("修改成功");
    }

    /**
     * 修改会员信息（会员名称、性别、生日）
     * 参数：*storeId, *memberId, name, sex（01.男02.女03.保密）, birthday（yyyy-MM-dd）
     */
    @ApiOperation(value = "修改会员信息", notes = "修改会员信息")
    @PostMapping("/updateUserInfo")
    public Result<?> updateUserInfo(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }
        String name = map.get("name") == null ? null : String.valueOf(map.get("name"));
        String sex = map.get("sex") == null ? null : String.valueOf(map.get("sex"));
        String birthday = map.get("birthday") == null ? null : String.valueOf(map.get("birthday"));
        String headPortrait = map.get("avatarUrl") == null ? null : String.valueOf(map.get("avatarUrl"));

        MemberManagement mm = new MemberManagement();
        mm.setId(memberId);
        mm.setName(name);
        mm.setSex(sex);
        mm.setBirthday(birthday);
        mm.setHeadPortrait(headPortrait);
        memberManagementService.updateById(mm);

        return Result.OK("修改成功");
    }

    /**
     * 修改会员名称
     * 参数：*storeId, *memberId, name
     */
    @ApiOperation(value = "修改会员名称", notes = "修改会员名称")
    @PostMapping("/updateUserName")
    public Result<?> updateUserName(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }
        String name = map.get("name") == null ? null : String.valueOf(map.get("name"));
        MemberManagement mm = new MemberManagement();
        mm.setId(memberId);
        mm.setName(name);
        mm.setNickName(name);
        memberManagementService.updateById(mm);

        return Result.OK("修改成功");
    }

    /**
     * 修改会员头像
     * 参数：*storeId, *memberId, name
     */
    @ApiOperation(value = "修改会员头像", notes = "修改会员头像")
    @PostMapping("/updateUserAvatar")
    public Result<?> updateUserAvatar(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }
        String headPortrait = map.get("avatarUrl") == null ? null : String.valueOf(map.get("avatarUrl"));

        MemberManagement mm = new MemberManagement();
        mm.setId(memberId);
        mm.setHeadPortrait(headPortrait);
        memberManagementService.updateById(mm);

        return Result.OK("修改成功");
    }

    /**
     * 已购商品（待取货、已取货、退款）
     */
    @ApiOperation(value = "已购商品（待取货、已取货、退款）", notes = "已购商品（待取货、已取货、退款）")
    @PostMapping("/listMemberCommodity")
    public Result<?> listMemberCommodity(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String orderStatus = map.get("orderStatus") == null ? null : String.valueOf(map.get("orderStatus"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(orderStatus)) {
            return Result.error("参数不全");
        }
        List<Map<String, Object>> list = appService.listMemberCommodity(map);
        for (Map<String, Object> m : list) {
            if (m.get("commodity_json_str") != null) {
                m.put("commodityJson", JSON.parseObject(String.valueOf(m.get("commodityJsonStr"))));
            }
        }

        return Result.OK(list);
    }

    /**
     * 已购项目（可用、已用完）
     * 参数：*storeId, *memberId, *type（1.可用2.已用完）
     */
    @ApiOperation(value = " 已购项目（可用、已用完）", notes = " 已购项目（可用、已用完）")
    @PostMapping("/listMemberProject")
    public Result<?> listMemberProject(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String type = map.get("type") == null ? null : String.valueOf(map.get("type"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(type)) {
            return Result.error("参数不全");
        }
        List<Map<String, Object>> list = appService.listMemberProject(map);

        for (Map<String, Object> m : list) {
            if (m.get("projectJsonStr") != null) {
                m.put("projectJson", JSON.parseObject(String.valueOf(m.get("projectJsonStr"))));
            }
            if (m.get("validateTime") == null){
                BaseOrderProject bop = baseOrderProjectService.getById(m.get("id").toString());

                List<BaseOrderServiceWriteoff> slist = baseOrderServiceWriteoffService.list(new QueryWrapper<BaseOrderServiceWriteoff>().eq("store_id", bop.getStoreId()).eq("order_project_id", bop.getOrderId()));
                if (slist.size() == 0 && m.get("timingWay").equals("2")){
                    m.put("left",m.get("indate"));
                }
            }else {
                Date validateTime =(Date) m.get("validateTime");
                int differDays = DateUtils.getDifferDays(new Date(), validateTime);
                m.put("left",differDays);
            }
        }

        return Result.OK(list);
    }

    /**
     * 项目中的商品、服务列表
     * 参数：*storeId, *orderProjectId
     */
    @ApiOperation(value = "项目中的商品、服务列表", notes = "项目中的商品、服务列表")
    @PostMapping("/listMemberProjectShopAndServe")
    public Result<?> listMemberProjectShopAndServe(@RequestBody Map<String, Object> map) {

        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String orderProjectId = map.get("orderProjectId") == null ? null : String.valueOf(map.get("orderProjectId"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(orderProjectId)) {
            return Result.error("参数不全");
        }

        List<BaseOrderServiceWriteoff> serveList = baseOrderServiceWriteoffService.list(new QueryWrapper<BaseOrderServiceWriteoff>()
                .eq("order_project_id", orderProjectId));

        List<BaseOrderCommodityWriteoff> commodityList1 = baseOrderCommodityWriteoffService.list(new QueryWrapper<BaseOrderCommodityWriteoff>()
                .eq("order_project_id", orderProjectId));

        List<Object> commodityList = commodityList1.stream().map(o -> {
            Map<String, Object> m = ToolsUtils.objectToMap(o);
            m.put("type", "1");
            return m;
        }).collect(Collectors.toList());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<BaseOrderWriteoffRecord> writeoffRecordList = baseOrderWriteoffRecordService.list(new QueryWrapper<BaseOrderWriteoffRecord>()
                .eq("order_project_id", orderProjectId));
        for (BaseOrderWriteoffRecord record : writeoffRecordList) {
            JSONArray cList = JSONArray.parseArray(record.getCommodityListJsonStr());
            for (int i = 0; i < cList.size(); i++) {
                JSONObject jsonObject = cList.getJSONObject(i);
                jsonObject.put("type", "2");
                jsonObject.put("writeoffTime", sdf.format(jsonObject.getDate("writeoffTime")));
                commodityList.add(cList.getJSONObject(i));
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("serveList", serveList);
        result.put("commodityList", commodityList);
        return Result.OK(result);
    }

    /**
     * 我的贵宾卡列表（自用、可赠送、可领取）
     */
    @ApiOperation(value = " 我的贵宾卡列表（自用、可赠送、可领取）", notes = " 我的贵宾卡列表（自用、可赠送、可领取）")
    @GetMapping(value = "/getMemberVipList")
    public Result<?> getVipList(@RequestParam(value = "cardId", required = false) String cardId
            , @RequestParam("storeId") String storeId
            , @RequestParam("memberId") String memberId
            , @RequestParam("type") String type) {
        List<Map<String, Object>> result = new ArrayList<>();
        if ("1".equals(type)) {
            List<BaseMemberVip> list = baseMemberVipService.list(new QueryWrapper<BaseMemberVip>()
                    .eq("store_id", storeId)
                    .eq("member_id", memberId)
                    .like(StringUtils.isNotEmpty(cardId), "card_id", cardId));

            for (BaseMemberVip ele : list) {
                Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(ele);

                Map<String, Object> style = getStyle(ele.getStoreId(), String.valueOf(ele.getCardId()));

                map.put("style", style);
                result.add(map);
            }
            return Result.OK(result);
        } else if ("2".equals(type)) {
            List<BaseMemberShareVip> list = baseMemberShareVipService.list(new QueryWrapper<BaseMemberShareVip>()
                    .eq("store_id", storeId)
                    .eq("member_id", memberId)
                    .eq("card_type", "通用卡")
                    .gt("num", 0)
                    .like(StringUtils.isNotEmpty(cardId), "card_id", cardId));
            for (BaseMemberShareVip ele : list) {
                Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(ele);

                Map<String, Object> style = getStyle(ele.getStoreId(), String.valueOf(ele.getCardId()));

                map.put("style", style);
                result.add(map);
            }
            return Result.OK(result);
        } else {
            List<BaseMemberToReceiveVip> list = baseMemberToReceiveVipService.list(new QueryWrapper<BaseMemberToReceiveVip>()
                    .eq("store_id", storeId)
                    .eq("member_id", memberId)
                    .eq("status", "0")
                    .like(StringUtils.isNotEmpty(cardId), "card_id", cardId));


            for (BaseMemberToReceiveVip ele : list) {
                Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(ele);

                Map<String, Object> style = getStyle(ele.getStoreId(), String.valueOf(ele.getCardId()));

                map.put("style", style);
                result.add(map);
            }

            return Result.OK(result);
        }
    }

    /**
     * 贵宾卡-优惠卷列表（自用、可赠送、可领取）
     */
    @ApiOperation(value = "贵宾卡-优惠卷列表（自用、可赠送、可领取）", notes = "贵宾卡-优惠卷列表（自用、可赠送、可领取）")
    @GetMapping(value = "/getCouponListByVip")
    public Result<?> getVipList(@RequestParam("storeId") String storeId, @RequestParam("vipId") String vipId, @RequestParam("type") String type) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");

        if ("1".equals(type)) {
            List<BaseMemberVipCoupon> list = baseMemberVipCouponService.list(new QueryWrapper<BaseMemberVipCoupon>().eq("member_vip_id", vipId));
            List<Map<String, Object>> result = list.stream()
                    // 使用完的优惠劵不展示
                    .filter(bmvc -> bmvc.getNum() > 0)
                    .map(bmvc -> {
                        Map<String, Object> m = ToolsUtils.objectToMap(bmvc);
                        // 优惠劵是否过期
                        m.put("isCouponOutTime", isCouponOutTime(bmvc));
                        Date fullDate = (Date) m.get("fullDate");
                        if (fullDate != null) {
                            m.put("fullDate", sdf2.format(fullDate));
                        }
                        Date fullNextDate = (Date) m.get("fullNextDate");
                        if (fullNextDate != null) {
                            m.put("fullNextDate", sdf2.format(fullNextDate));
                        }
                        Date createTime = (Date) m.get("createTime");
                        if (createTime != null) {
                            m.put("createTime", sdf.format(createTime));
                        }
                        Date updateTime = (Date) m.get("updateTime");
                        if (updateTime != null) {
                            m.put("updateTime", sdf.format(updateTime));
                        }
                        return m;
                    }).collect(Collectors.toList());
            return Result.OK(result);
        } else if ("2".equals(type)) {
            List<BaseMemberShareCoupon> list = baseMemberShareCouponService.list(new QueryWrapper<BaseMemberShareCoupon>().eq("share_vip_id", vipId));
            List<Map<String, Object>> result = list.stream()
                    // 使用完的优惠劵不展示
                    .filter(bmvc -> bmvc.getNum() > 0)
                    .map(bmvc -> {
                        Map<String, Object> m = ToolsUtils.objectToMap(bmvc);
                        // 优惠劵是否过期
                        m.put("isCouponOutTime", isCouponOutTime(bmvc));
                        Date fullDate = (Date) m.get("fullDate");
                        if (fullDate != null) {
                            m.put("fullDate", sdf2.format(fullDate));
                        }
                        Date fullNextDate = (Date) m.get("fullNextDate");
                        if (fullNextDate != null) {
                            m.put("fullNextDate", sdf2.format(fullNextDate));
                        }
                        Date createTime = (Date) m.get("createTime");
                        if (createTime != null) {
                            m.put("createTime", sdf.format(createTime));
                        }
                        Date updateTime = (Date) m.get("updateTime");
                        if (updateTime != null) {
                            m.put("updateTime", sdf.format(updateTime));
                        }
                        return m;
                    }).collect(Collectors.toList());
            return Result.OK(result);
        } else {
            List<BaseMemberToReceiveVipCoupon> list = baseMemberToReceiveVipCouponService.list(new QueryWrapper<BaseMemberToReceiveVipCoupon>().eq("to_receive_vip_id", vipId));
            List<Map<String, Object>> result = list.stream()
                    // 使用完的优惠劵不展示
                    .filter(bmtrvc -> bmtrvc.getNum() > 0)
                    .map(bmtrvc -> {
                        Map<String, Object> m = ToolsUtils.objectToMap(bmtrvc);
                        // 优惠劵是否过期
                        m.put("isCouponOutTime", isCouponOutTime(bmtrvc));
                        Date fullDate = (Date) m.get("fullDate");
                        if (fullDate != null) {
                            m.put("fullDate", sdf2.format(fullDate));
                        }
                        Date fullNextDate = (Date) m.get("fullNextDate");
                        if (fullNextDate != null) {
                            m.put("fullNextDate", sdf2.format(fullNextDate));
                        }
                        Date createTime = (Date) m.get("createTime");
                        if (createTime != null) {
                            m.put("createTime", sdf.format(createTime));
                        }
                        Date updateTime = (Date) m.get("updateTime");
                        if (updateTime != null) {
                            m.put("updateTime", sdf.format(updateTime));
                        }
                        return m;
                    }).collect(Collectors.toList());
            return Result.OK(result);
        }
    }

    /**
     * 贵宾卡详情
     */
    @ApiOperation(value = "贵宾卡详情", notes = "贵宾卡详情")
    @GetMapping(value = "/getVipDetail")
    public Result<?> getVipDetail(@RequestParam("vipId") String vipId, @RequestParam("type") String type) {

        if ("1".equals(type)) {
            BaseMemberVip vip = baseMemberVipService.getById(vipId);
            List<BaseMemberVipCoupon> couponList = baseMemberVipCouponService.list(new QueryWrapper<BaseMemberVipCoupon>().eq("member_vip_id", vipId));
//            List<BaseMemberVipCoupon> couponList2 = couponList.stream().filter(BaseMemberVipCoupon -> !BaseMemberVipCoupon.getNum().equals(0)).collect(Collectors.toList());
            List<BaseMemberVipCoupon> couponList2 = new ArrayList<>();
            List<Map> couponMapList = new ArrayList<>();
            for (BaseMemberVipCoupon coupon : couponList) {
                if (coupon.getNum() > 0) {
                    Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(coupon);
                    String ticketDetail = coupon.getTicketDetail();
                    String s = org.jeecg.modules.util.StringUtils.dealCoupon(ticketDetail);
                    map.put("shortTicketDetail", s);
                    couponMapList.add(map);
                }
            }

            Map<String, Object> resutMap = new HashMap<>();
            List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", vip.getStoreId()).eq("card_id", vip.getCardId()));
            if (list.size() > 0) {

                AllVipcard card = list.get(0);
                resutMap.put("card", card);
                Map<String, Object> styleMap = getStyleById(card.getStyleId());
                resutMap.put("style", styleMap);
            }


            resutMap.put("couponList", couponMapList);
            return Result.OK(resutMap);
        } else if ("2".equals(type)) {
            BaseMemberShareVip vip = baseMemberShareVipService.getById(vipId);
            List<BaseMemberShareCoupon> couponList = baseMemberShareCouponService.list(new QueryWrapper<BaseMemberShareCoupon>().eq("share_vip_id", vipId).eq(false, "num", 0));
//            List<BaseMemberShareCoupon> couponList2 = couponList.stream().filter(BaseMemberShareCoupon -> !BaseMemberShareCoupon.getNum().equals(0)).collect(Collectors.toList());
            List<BaseMemberShareCoupon> couponList2 = new ArrayList<>();
            List<Map> couponMapList = new ArrayList<>();
            for (BaseMemberShareCoupon coupon : couponList) {
                if (coupon.getNum() > 0) {
                    couponList2.add(coupon);
                    Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(coupon);
                    String ticketDetail = coupon.getTicketDetail();
                    String s = org.jeecg.modules.util.StringUtils.dealCoupon(ticketDetail);
                    map.put("shortTicketDetail", s);
                    couponMapList.add(map);
                }
            }

            Map<String, Object> resutMap = new HashMap<>();
            AllVipcard card = null;
            List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", vip.getStoreId()).eq("card_id", vip.getCardId()));
            if (list.size() > 0) {
                card = list.get(0);
                resutMap.put("card", card);
                Map<String, Object> styleMap = getStyleById(card.getStyleId());
                resutMap.put("style", styleMap);
            }
            resutMap.put("couponList", couponMapList);
            return Result.OK(resutMap);
        } else {
            BaseMemberToReceiveVip vip = baseMemberToReceiveVipService.getById(vipId);
            List<BaseMemberToReceiveVipCoupon> couponList = baseMemberToReceiveVipCouponService.list(new QueryWrapper<BaseMemberToReceiveVipCoupon>().eq("to_receive_vip_id", vipId).eq(false, "num", 0));
//            List<BaseMemberToReceiveVipCoupon> couponList2 = couponList.stream().filter(BaseMemberToReceiveVipCoupon -> !BaseMemberToReceiveVipCoupon.getNum().equals(0)).collect(Collectors.toList());
            List<BaseMemberToReceiveVipCoupon> couponList2 = new ArrayList<>();
            List<Map> couponMapList = new ArrayList<>();
            for (BaseMemberToReceiveVipCoupon coupon : couponList) {
                if (coupon.getNum() > 0) {
                    couponList2.add(coupon);
                    Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(coupon);
                    String ticketDetail = coupon.getTicketDetail();
                    String s = org.jeecg.modules.util.StringUtils.dealCoupon(ticketDetail);
                    map.put("shortTicketDetail", s);
                    couponMapList.add(map);

                }
            }
            Map<String, Object> resutMap = new HashMap<>();
            AllVipcard card = null;
            List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", vip.getStoreId()).eq("card_id", vip.getCardId()));
            if (list.size() > 0) {
                card = list.get(0);
                resutMap.put("card", card);
                Map<String, Object> styleMap = getStyleById(card.getStyleId());
                resutMap.put("style", styleMap);
            }

            resutMap.put("couponList", couponMapList);
            return Result.OK(resutMap);
        }
    }


    /**
     * 贵宾卡详情
     */
    @ApiOperation(value = "贵宾卡详情", notes = "贵宾卡详情")
    @GetMapping(value = "/getShareVideoDetail")
    public Result<?> getShareVideoDetail(@RequestParam("vipId") String vipId, @RequestParam("type") String type) {
        String shareVipVedioId = null;
        if ("3".equals(type)) {
            BaseMemberToReceiveVip toReceiveVip = baseMemberToReceiveVipService.getById(vipId);
            if (toReceiveVip == null) {
                return Result.error("未找到对应数据");
            }
            if (toReceiveVip.getShareVipId() == null) {
                String storeId = toReceiveVip.getStoreId();
                Integer cardId = toReceiveVip.getCardId();
                List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", storeId).eq("card_id", cardId));
                if (list.size() > 0) {
                    AllVipcard card = list.get(0);
                    shareVipVedioId = card.getVedioId();
                } else {
                    return Result.error("未找到对应数据");
                }
            }
            if (shareVipVedioId == null) {
                BaseMemberShareVip shareVip = baseMemberShareVipService.getById(toReceiveVip.getShareVipId());
                if (shareVip == null) {
                    return Result.error("未找到对应数据");
                }

                shareVipVedioId = shareVip.getVedioId();
            }
        } else if ("4".equals(type)) {
            BaseMemberShareVip shareVip = baseMemberShareVipService.getById(vipId);
            if (shareVip == null) {
                return Result.error("未找到对应数据");
            }
            shareVipVedioId = shareVip.getVedioId();
        }
        if (shareVipVedioId == null) {
            return Result.error("未找到视频ID");
        }
        VipCardVedio vipCardVedio = vipCardVedioService.getById(shareVipVedioId);
        if (vipCardVedio == null) {
            return Result.error("未找到对应数据");
        }


        JSONObject jsonObject = (JSONObject) JSON.toJSON(vipCardVedio);
        Map query = new HashMap();
        query.put("vedio_id", shareVipVedioId);


        Map<String, Object> map = convertVedio2Map(vipCardVedio);
        List list = vipCardVedioCommentService.listByMap(query);
        map.put("comments", list);

        return Result.OK(map);
    }

    /**
     * 领取贵宾卡
     */
    @ApiOperation(value = "领取贵宾卡", notes = "领取贵宾卡")
    @PostMapping(value = "/receiveVip")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> receiveVip(@RequestBody Map<String, Object> map) {

        log.info("receiveVip, map = {}", map);

        String toReceiveVipId = map.get("toReceiveVipId") == null ? null : String.valueOf(map.get("toReceiveVipId"));
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        if (StringUtils.isEmpty(toReceiveVipId) || StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId)) {
            return Result.error("参数不全");
        }

        BaseMemberToReceiveVip toReceiveVip = baseMemberToReceiveVipService.getById(toReceiveVipId);
        List<BaseMemberToReceiveVipCoupon> toReceiveCouponList = baseMemberToReceiveVipCouponService.list(new QueryWrapper<BaseMemberToReceiveVipCoupon>().eq("to_receive_vip_id", toReceiveVipId));
        MemberManagement member = memberManagementService.getById(memberId);

        // -------------------------------------- 校验逻辑 --------------------------------------
        if ("1".equals(toReceiveVip.getType())) {
            // 下发【通用卡，新人卡】
            if ("1".equals(toReceiveVip.getStatus())) {
                return Result.error("贵宾卡已领取过");
            }
        } else {
            // 分享【生成二维码，会员分享通用卡，股东分享拓客卡】
            if ("1".equals(toReceiveVip.getStatus())) {
                return Result.error("贵宾卡已被领光");
            }
            // 能否重复领取
            if ("否".equals(toReceiveVip.getCanCollectAgain()) && toReceiveVip.getShareMemberIds() != null) {
                String[] memberIds = toReceiveVip.getShareMemberIds().split(",");
                for (String memberId1 : memberIds) {
                    if (memberId.equals(memberId1)) {
                        return Result.error("贵宾卡不能重复领取");
                    }
                }
            }
        }
        // 是否仅限新客户领取
        if ("是".equals(toReceiveVip.getIsNewOnly()) || "股东拓客卡".equals(toReceiveVip.getCardType())) {
            if ("0".equals(member.getIsNew())) {
                return Result.error("贵宾卡仅限新客户领取");
            }
        }
        if (memberId.equals(toReceiveVip.getCreateMemberId())) {
            return Result.error("不可领取自己分享的贵宾卡");
        }

        // -------------------------------------- 领取逻辑 --------------------------------------

        Map<String, Object> result = new HashMap<>();

        if ("免费".equals(toReceiveVip.getIsFree())) {
            BaseMemberVip memberVip = new BaseMemberVip();
            BeanUtils.copyProperties(toReceiveVip, memberVip);
            memberVip.setId(null);
            memberVip.setCreateTime(null);
            memberVip.setCreateBy("xcx");
            memberVip.setUpdateTime(null);
            memberVip.setUpdateBy(null);
            memberVip.setUsed("0");
            memberVip.setMemberId(memberId);
            baseMemberVipService.save(memberVip);
            for (BaseMemberToReceiveVipCoupon toReceiveVipCoupon : toReceiveCouponList) {
                BaseMemberVipCoupon memberVipCoupon = new BaseMemberVipCoupon();
                BeanUtils.copyProperties(toReceiveVipCoupon, memberVipCoupon);
                memberVipCoupon.setId(null);
                memberVipCoupon.setCreateTime(null);
                memberVipCoupon.setCreateBy("xcx");
                memberVipCoupon.setUpdateTime(null);
                memberVipCoupon.setUpdateBy(null);
                memberVipCoupon.setMemberVipId(memberVip.getId());
                memberVipCoupon.setMemberId(memberId);
                baseMemberVipCouponService.save(memberVipCoupon);
            }
            // 其他关联信息处理 issuingRecordsId、status、shareNum、shareMemberIds、isRewardShareholders、shareVipId
            if (StringUtils.isNotEmpty(toReceiveVip.getIssuingRecordsId())) {
                IssuingRecords issuingRecords = issuingRecordsService.getById(toReceiveVip.getIssuingRecordsId());
                if (issuingRecords.getQuantityReceived() < issuingRecords.getCirculation()) {
                    issuingRecords.setQuantityReceived(issuingRecords.getQuantityReceived() + 1);
                }
                if (issuingRecords.getCurrentAllowance() > 0) {
                    issuingRecords.setCurrentAllowance(issuingRecords.getCurrentAllowance() - 1);
                }
                issuingRecordsService.updateById(issuingRecords);
                // PC下发通用卡，要处理可赠送数量

//                if ("通用卡".equals(toReceiveVip.getCardType()) && issuingRecords.getCirculation() > 1) {
//                    // 复制到会员/股东可分享贵宾卡
//                    BaseMemberShareVip bmsv = new BaseMemberShareVip();
//                    BeanUtils.copyProperties(toReceiveVip, bmsv);
//                    bmsv.setId(null);
//                    bmsv.setCreateBy("xcx");
//                    bmsv.setCreateTime(null);
//                    bmsv.setUpdateBy(null);
//                    bmsv.setUpdateTime(null);
//                    bmsv.setRecordId(issuingRecords.getId());
//                    bmsv.setMemberId(memberId);
//                    bmsv.setNum(issuingRecords.getCirculation() - 1);
//                    baseMemberShareVipService.save(bmsv);
//                    for (BaseMemberToReceiveVipCoupon toReceiveVipCoupon : toReceiveCouponList) {
//                        // 复制到会员/股东可分享贵宾卡关联的优惠劵表
//                        BaseMemberShareCoupon bmsc = new BaseMemberShareCoupon();
//                        BeanUtils.copyProperties(toReceiveVipCoupon, bmsc);
//                        bmsc.setId(null);
//                        bmsv.setCreateBy("xcx");
//                        bmsc.setCreateTime(null);
//                        bmsc.setUpdateBy(null);
//                        bmsc.setUpdateTime(null);
//                        bmsc.setShareVipId(bmsv.getId());
//                        bmsc.setMemberId(memberId);
//                        baseMemberShareCouponService.save(bmsc);
//                    }
//                }

            }
            if (StringUtils.isNotEmpty(toReceiveVip.getShareVipId())) {
                BaseMemberShareVip shareVip = baseMemberShareVipService.getById(toReceiveVip.getShareVipId());
                if (shareVip.getNum() > 0) {
                    shareVip.setNum(shareVip.getNum() - 1);
                }
                baseMemberShareVipService.updateById(shareVip);
            }
            if ("1".equals(toReceiveVip.getType())) {
                toReceiveVip.setStatus("1");
            } else {
                if (toReceiveVip.getShareNum() > 0) {
                    toReceiveVip.setShareNum(toReceiveVip.getShareNum() - 1);
                    if (toReceiveVip.getShareNum() <= 0) {
                        toReceiveVip.setStatus("1");
                    }
                }
                if (StringUtils.isNotEmpty(toReceiveVip.getShareMemberIds())) {
                    toReceiveVip.setShareMemberIds(toReceiveVip.getShareMemberIds() + "," + memberId);
                } else {
                    toReceiveVip.setShareMemberIds(memberId);
                }
            }
            baseMemberToReceiveVipService.updateById(toReceiveVip);

            if ("股东拓客卡".equals(toReceiveVip.getCardType())) {
                //if ("2".equals(member.getStatus())) {
                MemberManagement createMember = memberManagementService.getById(toReceiveVip.getCreateMemberId());
                member.setMemberType("股东会员");
                member.setStatus("1");
                member.setStockId(createMember.getMyStockId());
                member.setHighStockId(createMember.getStockId());//上级
                // 模板消息
                try {
                    MemberManagement stockMember = memberManagementService.getById(toReceiveVip.getCreateMemberId());
                    String gzhOpenId = stockMember.getGzhOpenId();
                    if (gzhOpenId == null) {
                        log.info("发送成为股东会员模板推送失败，股东未绑定公众号");
                    } else {
                        StoreInfo store = storeInfoService.getById(stockMember.getStoreId());
                        String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
                        if (store == null) {
                            log.info("发送成为股东会员模板推送失败，未查到店铺信息");
                        } else {
                            String gzhAppId = store.getGzhAppId();
                            String gzhAppSecret = store.getGzhAppSecret();
                            if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                log.info("发送成为股东会员模板推送失败，店铺未绑定公众号");
                            } else {
                                String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                String result1 = HttpUtils.sendGet(url1);
                                JSONObject resultJson1 = JSON.parseObject(result1);
                                String errcode = resultJson1.getString("errcode");
                                if (errcode != null && !"0".equals(errcode)) {
                                    log.info("发送成为股东会员模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                } else {
                                    String accessToken = resultJson1.getString("access_token");
                                    String memberPhone = member.getPhone();
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                    MsgTemplate msgTemplate = msgTemplateListService.getByTitle("推荐会员成功提醒", storeId);
                                    String templateId = msgTemplate.getTemplateId();
                                    util.recommendMemberSuccessNotice(templateId, gzhOpenId, memberPhone.substring(0, 3) + "****" + memberPhone.substring(7), sdf.format(new Date()), store.getXcxAppId(), "user/share/tourist", accessToken);
                                    String stockId = createMember.getMyStockId();
                                    if (stockId != null && stockId != "") {
                                        StockManage stockManage = stockManageService.getById(stockId);
                                        MsgTemplate msgTemplate2 = msgTemplateListService.getByTitle("新增成员提醒", storeId);
                                        String templateId2 = msgTemplate2.getTemplateId();

                                        util.addMemberNotice(templateId2, bossGzhOpenId, memberPhone.substring(0, 3) + "****" + memberPhone.substring(7), sdf.format(new Date()), stockManage.getStockName(), store.getXcxAppId(), "", accessToken);
                                    }
                                    log.info("发送成为股东会员模板推送成功");
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("发送成为股东会员模板推送失败，发生异常", e);
                }
                //}
            }
            member.setIsNew("0");
            member.setUpdateBy("xcx");
            memberManagementService.updateById(member);

            VipcardDrawRecord vipcardDrawRecord = new VipcardDrawRecord();
            vipcardDrawRecord.setCreateBy("xcx");
            vipcardDrawRecord.setCreateTime(new Date());
            vipcardDrawRecord.setMemberId(member.getId());
            vipcardDrawRecord.setStoreId(storeId);
            vipcardDrawRecord.setVipId(getVipId(toReceiveVip.getStoreId(), toReceiveVip.getCardId()));
            vipcardDrawRecord.setIssuingRecordsId(toReceiveVip.getIssuingRecordsId());
            vipcardDrawRecord.setDrawDate(new Date());
            vipcardDrawRecord.setRemark("method receiveVip");
            vipcardDrawRecordService.save(vipcardDrawRecord);

            result.put("payParams", null);
            return Result.OK("领取成功", result);
        } else {
            // 贵宾卡需要付费
            StoreInfo store = storeInfoService.getById(storeId);
            if (store == null) {
                return Result.error("店铺不存在");
            }
            String xcxAppId = store.getXcxAppId();
            if (StringUtils.isEmpty(xcxAppId)) {
                return Result.error("店铺还未绑定小程序");
            }
            String saobeiMerchantNo = store.getSaobeiMerchantNo();
            String saobeiTerminalId = store.getSaobeiTerminalId();
            String saobeiAccessToken = store.getSaobeiAccessToken();
            if (StringUtils.isEmpty(saobeiMerchantNo) || StringUtils.isEmpty(saobeiTerminalId) || StringUtils.isEmpty(saobeiAccessToken)) {
                return Result.error("店铺还未绑定支付");
            }
            String xcxOpenId = member.getXcxOpenId();
            if (StringUtils.isEmpty(xcxOpenId)) {
                return Result.error("会员还未绑定小程序");
            }

//            member.setIsNew("0");
//            member.setUpdateBy("xcx");
//            memberManagementService.updateById(member);

            VipOrderRecord vipOrderRecord = new VipOrderRecord();
            vipOrderRecord.setOrderCode(ToolsUtils.getBillNo("VO"));
            vipOrderRecord.setOrderStatus("0");
            vipOrderRecord.setToReceiveVipId(toReceiveVipId);
            vipOrderRecord.setSellingPrice(toReceiveVip.getSellingPrice());
            vipOrderRecord.setMemberId(memberId);
            vipOrderRecord.setStoreId(storeId);
            vipOrderRecord.setCreateBy("xcx");
            vipOrderRecordService.save(vipOrderRecord);

            System.out.println("lukasli: {}" + JSONObject.toJSON(vipOrderRecord));

            BigDecimal sellingPrice = new BigDecimal(String.valueOf(toReceiveVip.getSellingPrice()));
            String totalFee = String.valueOf(sellingPrice.multiply(new BigDecimal("100")).intValue());

            SaobeiMiniPayResponse minipayResponse = Saobei.minipay(saobeiAccessToken, saobeiMerchantNo, saobeiTerminalId, xcxAppId, xcxOpenId, toReceiveVip.getCardName(), vipOrderRecord.getId(), totalFee);
            if ("01".equals(minipayResponse.getResult_code())) {
                SaobeiOrderRecord saobeiOrderRecord = new SaobeiOrderRecord();
                saobeiOrderRecord.setType("6");
                saobeiOrderRecord.setOutTradeNo(minipayResponse.getOut_trade_no());
                saobeiOrderRecord.setTerminalTrace(vipOrderRecord.getId());
                saobeiOrderRecord.setTotalFee(totalFee);
                saobeiOrderRecord.setStoreId(storeId);
                saobeiOrderRecord.setCreateBy("xcx");
                saobeiOrderRecordService.save(saobeiOrderRecord);

                Map<String, Object> payParams = new HashMap<>();
                payParams.put("timeStamp", minipayResponse.getTimeStamp());
                payParams.put("nonceStr", minipayResponse.getNonceStr());
                payParams.put("package_str", minipayResponse.getPackage_str());
                payParams.put("signType", minipayResponse.getSignType());
                payParams.put("paySign", minipayResponse.getPaySign());
                result.put("payParams", payParams);

                VipcardDrawRecord vipcardDrawRecord = new VipcardDrawRecord();
                vipcardDrawRecord.setCreateBy("xcx");
                vipcardDrawRecord.setCreateTime(new Date());
                vipcardDrawRecord.setMemberId(member.getId());
                vipcardDrawRecord.setStoreId(storeId);
                vipcardDrawRecord.setIssuingRecordsId(toReceiveVip.getIssuingRecordsId());
                vipcardDrawRecord.setVipId(getVipId(toReceiveVip.getStoreId(), toReceiveVip.getCardId()));
                vipcardDrawRecord.setDrawDate(new Date());
                vipcardDrawRecord.setRemark("vipOrderRecordId[" + vipOrderRecord.getId() + "]  saobeiOrderRecordId[" + saobeiOrderRecord.getId() + "]");
                vipcardDrawRecordService.save(vipcardDrawRecord);

                return Result.OK("跳转支付", result);
            } else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return Result.error("生成扫呗订单失败：" + minipayResponse.getReturn_msg());
            }
        }

    }

    /**
     * 支付回调
     */
    @ApiOperation(value = "支付回调", notes = "支付回调")
    @PostMapping(value = "/saobeiCallback", consumes = {MediaType.TEXT_XML_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
    @Transactional(rollbackFor = Exception.class)
    public String saobeiCallback(@RequestBody String body) {

        log.info("saobeiCallback调用,body = {}", body);
        Map<String, Object> result = new HashMap<>();
        result.put("return_code", "01");
        result.put("return_msg", "接收成功");
        System.out.println("lukasli: saobeiCallback调用,body = " + body);
        try {
            JSONObject json = JSON.parseObject(body);
            String outTradeNo = json.getString("out_trade_no");
            String terminalTrace = json.getString("terminal_trace");
            SaobeiOrderRecord saobeiOrderRecord = saobeiOrderRecordService.getOne(new QueryWrapper<SaobeiOrderRecord>().eq("out_trade_no", outTradeNo));
            if (saobeiOrderRecord == null) {
                saobeiOrderRecord = saobeiOrderRecordService.getOne(new QueryWrapper<SaobeiOrderRecord>().eq("terminal_trace", terminalTrace));
                if (saobeiOrderRecord == null) {
                    return JSON.toJSONString(result);
                }
            }
//            BasePayOrder payOrder = basePayOrderService.getById(terminalTrace);
//            payOrder.setPayTime(Date.from(Instant.now()));
//            payOrder.setPayCode(outTradeNo);
//            basePayOrderService.updateById(payOrder);

            String resultCode = json.getString("result_code");
            if (!"01".equals(resultCode)) {
                // 结果不为成功
                saobeiOrderRecord.setResultCode(resultCode);
                saobeiOrderRecord.setUpdateBy("xcx");
                saobeiOrderRecordService.updateById(saobeiOrderRecord);
                return JSON.toJSONString(result);
            }
            String receiptFee = json.getString("receipt_fee");
            saobeiOrderRecord.setReceiptFee(receiptFee);
            saobeiOrderRecord.setResultCode(resultCode);
            saobeiOrderRecord.setUpdateBy("xcx");
            saobeiOrderRecordService.updateById(saobeiOrderRecord);

            BasePayOrder payOrder = basePayOrderService.getById(terminalTrace);
            payOrder.setPayTime(Date.from(Instant.now()));
            payOrder.setPayCode(outTradeNo);
            log.info("saobeiCallback  payOrder:{}", JSON.toJSONString(payOrder));
            basePayOrderService.updateById(payOrder);

            String type = saobeiOrderRecord.getType();
            if ("1".equals(type)) {
                // 店铺续费
                RechargeRecord rechargeRecord = rechargeRecordService.getById(saobeiOrderRecord.getTerminalTrace());
                StoreInfo store = storeInfoService.getById(rechargeRecord.getStoreId());
                Date now = new Date();
                Date storeExpiryDate = store.getStoreExpiryDate();
                boolean expired = now.compareTo(storeExpiryDate) >= 0;

                // 已过期的话，从当前时间开始增加有效期；未过期则直接累加
                Date date1 = expired ? new Date() : store.getStoreExpiryDate();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date1);
                String rechargeType = rechargeRecord.getRechargeType();
                if (rechargeType.equals("年卡")) {
                    calendar.add(Calendar.YEAR, 1);
                }
                if (rechargeType.equals("半年卡")) {
                    calendar.add(Calendar.MONTH, 6);
                }
                if (rechargeType.equals("季度卡")) {
                    calendar.add(Calendar.MONTH, 3);
                }
                if (rechargeType.equals("月卡")) {
                    calendar.add(Calendar.MONTH, 1);
                }
                rechargeRecord.setRechargeTime(new Date());
                rechargeRecord.setOrderStatus("1");
                rechargeRecord.setPayCode(outTradeNo);
                rechargeRecordService.updateById(rechargeRecord);

                store.setStoreExpiryDate(calendar.getTime());
                storeInfoService.updateById(store);
            } else if ("5".equals(type)) {
                // 小程序支付订单
                BaseOrder baseOrder = baseOrderService.getById(saobeiOrderRecord.getTerminalTrace());
                if (baseOrder == null) {
                    return JSON.toJSONString(result);
                }
                Map<String, Object> params = new HashMap<>();
                params.put("orderId", saobeiOrderRecord.getTerminalTrace());
                params.put("payType", "微信支付");
                params.put("outTradeNo", outTradeNo);
                payOrder(params);
            } else if ("6".equals(type)) {
                // 小程序支付贵宾卡
                VipOrderRecord vipOrderRecord = vipOrderRecordService.getById(saobeiOrderRecord.getTerminalTrace());
                if (vipOrderRecord == null) {
                    return JSON.toJSONString(result);
                }

                String toReceiveVipId = vipOrderRecord.getToReceiveVipId();
                BaseMemberToReceiveVip toReceiveVip = baseMemberToReceiveVipService.getById(toReceiveVipId);
                List<BaseMemberToReceiveVipCoupon> toReceiveCouponList = baseMemberToReceiveVipCouponService.list(new QueryWrapper<BaseMemberToReceiveVipCoupon>().eq("to_receive_vip_id", toReceiveVipId));
                String memberId = vipOrderRecord.getMemberId();
                MemberManagement member = memberManagementService.getById(memberId);

                BaseMemberVip memberVip = new BaseMemberVip();
                BeanUtils.copyProperties(toReceiveVip, memberVip);
                memberVip.setId(null);
                memberVip.setCreateTime(null);
                memberVip.setCreateBy("xcx");
                memberVip.setUpdateTime(null);
                memberVip.setUpdateBy(null);
                memberVip.setUsed("0");
                memberVip.setMemberId(memberId);
                baseMemberVipService.save(memberVip);
                for (BaseMemberToReceiveVipCoupon toReceiveVipCoupon : toReceiveCouponList) {
                    BaseMemberVipCoupon memberVipCoupon = new BaseMemberVipCoupon();
                    BeanUtils.copyProperties(toReceiveVipCoupon, memberVipCoupon);
                    memberVipCoupon.setId(null);
                    memberVipCoupon.setCreateTime(null);
                    memberVipCoupon.setCreateBy("xcx");
                    memberVipCoupon.setUpdateTime(null);
                    memberVipCoupon.setUpdateBy(null);
                    memberVipCoupon.setMemberVipId(memberVip.getId());
                    memberVipCoupon.setMemberId(memberId);
                    baseMemberVipCouponService.save(memberVipCoupon);
                }
                // 其他关联信息处理 issuingRecordsId、status、shareNum、shareMemberIds、isRewardShareholders、shareVipId
                if (StringUtils.isNotEmpty(toReceiveVip.getIssuingRecordsId())) {
                    IssuingRecords issuingRecords = issuingRecordsService.getById(toReceiveVip.getIssuingRecordsId());
                    if (issuingRecords.getQuantityReceived() < issuingRecords.getCirculation()) {
                        issuingRecords.setQuantityReceived(issuingRecords.getQuantityReceived() + 1);
                    }
                    if (issuingRecords.getCurrentAllowance() > 0) {
                        issuingRecords.setCurrentAllowance(issuingRecords.getCurrentAllowance() - 1);
                    }
                    issuingRecordsService.updateById(issuingRecords);
                    // PC下发通用卡，要处理可赠送数量

//                    if ("通用卡".equals(toReceiveVip.getCardType()) && issuingRecords.getCirculation() > 1) {
//                        // 复制到会员/股东可分享贵宾卡
//                        BaseMemberShareVip bmsv = new BaseMemberShareVip();
//                        BeanUtils.copyProperties(toReceiveVip, bmsv);
//                        bmsv.setId(null);
//                        bmsv.setCreateBy("xcx");
//                        bmsv.setCreateTime(null);
//                        bmsv.setUpdateBy(null);
//                        bmsv.setUpdateTime(null);
//                        bmsv.setRecordId(issuingRecords.getId());
//                        bmsv.setMemberId(memberId);
//                        bmsv.setNum(issuingRecords.getCirculation() - 1);
//                        baseMemberShareVipService.save(bmsv);
//                        for (BaseMemberToReceiveVipCoupon toReceiveVipCoupon : toReceiveCouponList) {
//                            // 复制到会员/股东可分享贵宾卡关联的优惠劵表
//                            BaseMemberShareCoupon bmsc = new BaseMemberShareCoupon();
//                            BeanUtils.copyProperties(toReceiveVipCoupon, bmsc);
//                            bmsc.setId(null);
//                            bmsv.setCreateBy("xcx");
//                            bmsc.setCreateTime(null);
//                            bmsc.setUpdateBy(null);
//                            bmsc.setUpdateTime(null);
//                            bmsc.setShareVipId(bmsv.getId());
//                            bmsc.setMemberId(memberId);
//                            baseMemberShareCouponService.save(bmsc);
//                        }
//                    }

                }

                //kevin 20220626
                if (StringUtils.isNotEmpty(toReceiveVip.getShareVipId())) {
                    BaseMemberShareVip shareVip = baseMemberShareVipService.getById(toReceiveVip.getShareVipId());
                    if (shareVip.getNum() > 0) {
                        shareVip.setNum(shareVip.getNum() - 1);
                    }
                    baseMemberShareVipService.updateById(shareVip);
                }
                if ("1".equals(toReceiveVip.getType())) {
                    toReceiveVip.setStatus("1");
                } else {
                    if (toReceiveVip.getShareNum() > 0) {
                        toReceiveVip.setShareNum(toReceiveVip.getShareNum() - 1);
                        if (toReceiveVip.getShareNum() <= 0) {
                            toReceiveVip.setStatus("1");
                        }
                    }
                    if (StringUtils.isNotEmpty(toReceiveVip.getShareMemberIds())) {
                        toReceiveVip.setShareMemberIds(toReceiveVip.getShareMemberIds() + "," + memberId);
                    } else {
                        toReceiveVip.setShareMemberIds(memberId);
                    }
                }
                baseMemberToReceiveVipService.updateById(toReceiveVip);

                if ("是".equals(toReceiveVip.getIsRewardShareholders()) && StringUtils.isNotEmpty(toReceiveVip.getBonusStockId()) && toReceiveVip.getShareholdersBonus() != null) {
                    StockManage stock = stockManageService.getById(toReceiveVip.getBonusStockId());
                    BigDecimal shareholdersBonus = new BigDecimal(String.valueOf(toReceiveVip.getShareholdersBonus()));
                    BigDecimal totalDividend = new BigDecimal(String.valueOf(stock.getTotalDividend()));
                    stock.setTotalDividend(totalDividend.add(shareholdersBonus).doubleValue());
                    BigDecimal canWithdrawal = new BigDecimal(String.valueOf(stock.getCanWithdrawal()));
                    stock.setCanWithdrawal(canWithdrawal.add(shareholdersBonus).doubleValue());
                    stock.setUpdateBy("xcx");
                    stockManageService.updateById(stock);
                    vipOrderRecord.setShareholdersBonus(toReceiveVip.getShareholdersBonus());
                    vipOrderRecord.setBonusStockId(toReceiveVip.getBonusStockId());

                    // 模板消息
                    try {
                        MemberManagement mm1 = memberManagementService.getById(stock.getMemberId());
                        String gzhOpenId = mm1.getGzhOpenId();
                        if (gzhOpenId == null) {
                            log.info("发送分红提醒模板推送失败，会员未绑定公众号");
                        } else {
                            StoreInfo store = storeInfoService.getById(stock.getStoreId());
                            if (store == null) {
                                log.info("发送分红提醒模板推送失败，未查到店铺信息");
                            } else {
                                String bossGzhOpenId = storeInfoService.getBossGzhOpenId(stock.getStoreId());
                                String gzhAppId = store.getGzhAppId();
                                String gzhAppSecret = store.getGzhAppSecret();
                                if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                    log.info("发送分红提醒模板推送失败，店铺未绑定公众号");
                                } else {
                                    String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                    String result1 = HttpUtils.sendGet(url1);
                                    JSONObject resultJson1 = JSON.parseObject(result1);
                                    String errcode = resultJson1.getString("errcode");
                                    if (errcode != null && !"0".equals(errcode)) {
                                        log.info("发送分红提醒模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                    } else {
                                        String accessToken = resultJson1.getString("access_token");
                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                        MsgTemplate msgTemplate = msgTemplateListService.getByTitle("订单分红提醒", store.getId());
                                        String templateId = msgTemplate.getTemplateId();
                                        util.orderDividendNotice(templateId, gzhOpenId, String.valueOf(shareholdersBonus), String.valueOf(stock.getTotalDividend()), sdf.format(new Date()), store.getXcxAppId(), "user/share/bonus", accessToken);

                                        log.info("发送分红提醒模板推送成功");
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("发送分红提醒模板推送失败，发生异常", e);
                    }
                }

                if ("股东拓客卡".equals(toReceiveVip.getCardType())) {
                    //if ("2".equals(member.getStatus())) {
                    MemberManagement createMember = memberManagementService.getById(toReceiveVip.getCreateMemberId());
                    member.setMemberType("股东会员");
                    member.setStatus("1");
                    member.setStockId(createMember.getMyStockId());
                    // 模板消息
                    try {
                        MemberManagement stockMember = memberManagementService.getById(toReceiveVip.getCreateMemberId());
                        String gzhOpenId = stockMember.getGzhOpenId();
                        if (gzhOpenId == null) {
                            log.info("发送成为股东会员模板推送失败，股东未绑定公众号");
                        } else {
                            StoreInfo store = storeInfoService.getById(createMember.getStoreId());
                            if (store == null) {
                                log.info("发送成为股东会员模板推送失败，未查到店铺信息");
                            } else {
                                String bossGzhOpenId = storeInfoService.getBossGzhOpenId(store.getId());
                                String gzhAppId = store.getGzhAppId();
                                String gzhAppSecret = store.getGzhAppSecret();
                                if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                                    log.info("发送成为股东会员模板推送失败，店铺未绑定公众号");
                                } else {
                                    String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                                    String result1 = HttpUtils.sendGet(url1);
                                    JSONObject resultJson1 = JSON.parseObject(result1);
                                    String errcode = resultJson1.getString("errcode");
                                    if (errcode != null && !"0".equals(errcode)) {
                                        log.info("发送成为股东会员模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                                    } else {
                                        String accessToken = resultJson1.getString("access_token");
                                        String memberPhone = member.getPhone();
                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                                        MsgTemplate msgTemplate = msgTemplateListService.getByTitle("推荐会员成功提醒", store.getId());
                                        String templateId = msgTemplate.getTemplateId();
                                        util.recommendMemberSuccessNotice(templateId, gzhOpenId, memberPhone.substring(0, 3) + "****" + memberPhone.substring(7), sdf.format(new Date()), store.getXcxAppId(), "user/share/tourist", accessToken);
                                        String stockId = createMember.getMyStockId();
                                        if (stockId != null && stockId != "") {
                                            StockManage stockManage = stockManageService.getById(stockId);
                                            MsgTemplate msgTemplate2 = msgTemplateListService.getByTitle("新增成员提醒", store.getId());
                                            String templateId2 = msgTemplate2.getTemplateId();
                                            util.addMemberNotice(templateId2, bossGzhOpenId, memberPhone.substring(0, 3) + "****" + memberPhone.substring(7), sdf.format(new Date()), stockManage.getStockName(), store.getXcxAppId(), "", accessToken);
                                        }
                                        log.info("发送成为股东会员模板推送成功");
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("发送成为股东会员模板推送失败，发生异常", e);
                    }
                    //}
                }
                member.setIsNew("0");
                member.setUpdateBy("xcx");
                memberManagementService.updateById(member);

                vipOrderRecord.setOrderStatus("1");
                vipOrderRecord.setUpdateBy("xcx");
                vipOrderRecord.setPayCode(outTradeNo);
                vipOrderRecordService.updateById(vipOrderRecord);
            }

            return JSON.toJSONString(result);
        } catch (Exception e) {
            log.error("[body = {}]回调发生异常", body, e);
            result.put("return_code", "02");
            result.put("return_msg", e.getMessage());
            return JSON.toJSONString(result);
        }
    }

    /**
     * 分享贵宾卡
     */
    @ApiOperation(value = "分享贵宾卡", notes = "分享贵宾卡")
    @PostMapping(value = "/shareVip")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> shareVip(@RequestBody Map<String, Object> map, HttpServletResponse res) {

        String shareVipId = map.get("shareVipId") == null ? null : String.valueOf(map.get("shareVipId"));
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String type = map.get("type") == null ? null : String.valueOf(map.get("type"));
        //String env_version = map.get("env_version") == null ? null : String.valueOf(map.get("env_version"));
        System.out.println("shareVipId:" + shareVipId + " ,storeId:" + storeId + ",memberId:" + memberId + ",type:" + type);
        String env_version = "release";
        String page = map.get("page") == null ? null : String.valueOf(map.get("page"));
        if (StringUtils.isEmpty(shareVipId) || StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(type)) {
            return Result.error("参数不全");
        }
        if ("1".equals(type) && (StringUtils.isEmpty(env_version) || StringUtils.isEmpty(page))) {
            return Result.error("参数不全");
        }


        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("店铺不存在");
        }
        String xcxAppId = store.getXcxAppId();
        String xcxAppSecret = store.getXcxAppSecret();
        if (StringUtils.isEmpty(xcxAppId) || StringUtils.isEmpty(xcxAppSecret)) {
            return Result.error("店铺还未绑定小程序");
        }
        AllVipcard vipCard = null;

//        List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", storeId).eq("card_id", shareVipId));

        BaseMemberShareVip byId = baseMemberShareVipService.getById(shareVipId);

        List<AllVipcard> list = appService.getCard(storeId, byId.getCardId().toString());

        System.out.println("LukasLi ，长度 " + list.size());
        if (list.size() <= 0) {
            return Result.error("没有对应的贵宾卡");
        }
        vipCard = list.get(0);

        BaseMemberToReceiveVip oldToReceiveVip = baseMemberToReceiveVipService.getOne(new QueryWrapper<BaseMemberToReceiveVip>().eq("share_vip_id", shareVipId));
        if (oldToReceiveVip != null) {
            if ("1".equals(type)) {
                String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + xcxAppId + "&secret=" + xcxAppSecret;
                String result1 = HttpUtils.sendGet(url1);
                JSONObject resultJson1 = JSON.parseObject(result1);
                String errcode = resultJson1.getString("errcode");
                if (errcode != null && !"0".equals(errcode)) {
                    log.debug("获取accessToken返回值异常，错误码：{}", errcode);
                    return Result.error("获取accessToken返回值异常，错误码：" + errcode + "result：" + resultJson1);
                }
                String accessToken = resultJson1.getString("access_token");

                String url2 = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
                JSONObject params1 = new JSONObject();

                if (hasVedio(vipCard)) {
                    params1.put("scene", "vipId=" + oldToReceiveVip.getId() + "&type=3");
                    params1.put("page", "pages/shipin/index");
                } else {
                    params1.put("scene", "vipId=" + oldToReceiveVip.getId() + "&type=3");
                    params1.put("page", page);
                }
                params1.put("check_path", false);
                params1.put("env_version", env_version);
                params1.put("is_hyaline", true);
                System.out.println("生成二维码的地址:" + url2);
                HttpUtils.sendPostJsonWriteRes(params1, url2, res);
                return null;
            } else {
                Map<String, Object> result = new HashMap<>();
                result.put("toReceiveVipId", oldToReceiveVip.getId());

                if (hasVedio(vipCard)) {
                    result.put("vId", vipCard.getVedioId());
                    VipCardVedio vedio = vipCardVedioService.getById(vipCard.getVedioId());
                    result.put("vedioPath", vedio.getVedioPath());
                } else {
                    result.put("vId", "0");
                }
                return Result.OK(result);
            }
        }

        BaseMemberShareVip shareVip = baseMemberShareVipService.getById(shareVipId);
        List<BaseMemberShareCoupon> shareCouponList = baseMemberShareCouponService.list(new QueryWrapper<BaseMemberShareCoupon>().eq("share_vip_id", shareVipId));

        BaseMemberToReceiveVip toReceiveVip = new BaseMemberToReceiveVip();
        BeanUtils.copyProperties(shareVip, toReceiveVip);
        toReceiveVip.setId(null);
        toReceiveVip.setCreateTime(null);
        toReceiveVip.setCreateBy("xcx");
        toReceiveVip.setUpdateTime(null);
        toReceiveVip.setUpdateBy(null);
        toReceiveVip.setType("2");
        toReceiveVip.setStatus("0");
        toReceiveVip.setShareNum(shareVip.getNum());
        // 如果待分享贵宾卡stockId不为空，则复制到toReceiveVip中
        toReceiveVip.setBonusStockId(shareVip.getStockId());
        toReceiveVip.setShareVipId(shareVip.getId());
        toReceiveVip.setIssuingRecordsId(shareVip.getRecordId());
        toReceiveVip.setMemberId(null);
        toReceiveVip.setCreateMemberId(memberId);
        baseMemberToReceiveVipService.save(toReceiveVip);
        for (BaseMemberShareCoupon shareCoupon : shareCouponList) {
            BaseMemberToReceiveVipCoupon toReceiveVipCoupon = new BaseMemberToReceiveVipCoupon();
            BeanUtils.copyProperties(shareCoupon, toReceiveVipCoupon);
            toReceiveVipCoupon.setId(null);
            toReceiveVipCoupon.setCreateTime(null);
            toReceiveVipCoupon.setCreateBy(null);
            toReceiveVipCoupon.setUpdateTime(null);
            toReceiveVipCoupon.setUpdateBy(null);
            toReceiveVipCoupon.setToReceiveVipId(toReceiveVip.getId());
            baseMemberToReceiveVipCouponService.save(toReceiveVipCoupon);
        }

        if ("1".equals(type)) {
            String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + xcxAppId + "&secret=" + xcxAppSecret;
            String result1 = HttpUtils.sendGet(url1);
            JSONObject resultJson1 = JSON.parseObject(result1);
            String errcode = resultJson1.getString("errcode");
            if (errcode != null && !"0".equals(errcode)) {
                log.debug("获取accessToken返回值异常，错误码：{}", errcode);
                return Result.error("获取accessToken返回值异常，错误码：" + errcode + "result：" + resultJson1);
            }
            String accessToken = resultJson1.getString("access_token");

            String url2 = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
            JSONObject params1 = new JSONObject();
            if (hasVedio(vipCard)) {
                //贵宾视频卡
                VipCardVedio vedio = vipCardVedioService.getById(vipCard.getVedioId());
                params1.put("page", "pages/shipin/index");
                params1.put("scene", "vipId=" + toReceiveVip.getId() + "&type=3&vedioId=" + vipCard.getVedioId());
                //params1.put("page2", "pages/shipin/index");
            } else {
                params1.put("page", page);
                params1.put("scene", "vipId=" + toReceiveVip.getId() + "&type=3");
            }

            params1.put("check_path", false);
            params1.put("env_version", env_version);
            params1.put("is_hyaline", true);
            HttpUtils.sendPostJsonWriteRes(params1, url2, res);
            return null;
        } else {
            Map<String, Object> result = new HashMap<>();
            result.put("toReceiveVipId", toReceiveVip.getId());
            return Result.OK(result);
        }
    }

    private boolean hasVedio(AllVipcard av) {
        return av.getVedioId() != null && av.getVedioId().trim().length() > 0;
    }

    private boolean isBlank(String vedioId) {
        return vedioId == null || vedioId.trim().length() == 0;
    }

    private boolean isCouponOutTime(BaseMemberVipCoupon bmvc) {
        if ("0".equals(bmvc.getFullSelect())) {
            // x年x月-x年x月
            Date endDate = bmvc.getFullNextDate();
            Date now = new Date();
            return now.after(endDate);
        }
        if ("1".equals(bmvc.getFullSelect())) {
            // 领取x天以内
            Date createTime = bmvc.getCreateTime();
            Integer day = Integer.valueOf(bmvc.getManualDateNum());
            Calendar c = Calendar.getInstance();
            c.setTime(createTime);
            c.add(Calendar.DAY_OF_MONTH, day);
            Date endDate = c.getTime();
            Date now = new Date();
            return now.after(endDate);
        }
        // 永久有效
        return false;
    }

    private boolean isCouponOutTime(BaseMemberShareCoupon bmvc) {
        if ("0".equals(bmvc.getFullSelect())) {
            // x年x月-x年x月
            Date endDate = bmvc.getFullNextDate();
            Date now = new Date();
            return now.after(endDate);
        }
        if ("1".equals(bmvc.getFullSelect())) {
            // 领取x天以内
            Date createTime = bmvc.getCreateTime();
            Integer day = Integer.valueOf(bmvc.getManualDateNum());
            Calendar c = Calendar.getInstance();
            c.setTime(createTime);
            c.add(Calendar.DAY_OF_MONTH, day);
            Date endDate = c.getTime();
            Date now = new Date();
            return now.after(endDate);
        }
        // 永久有效
        return false;
    }

    private boolean isCouponOutTime(BaseMemberToReceiveVipCoupon bmtrvc) {
        if ("0".equals(bmtrvc.getFullSelect())) {
            // x年x月-x年x月
            Date endDate = bmtrvc.getFullNextDate();
            Date now = new Date();
            return now.after(endDate);
        }
        if ("1".equals(bmtrvc.getFullSelect())) {
            // 领取x天以内
            Date createTime = bmtrvc.getCreateTime();
            Integer day = Integer.valueOf(bmtrvc.getManualDateNum());
            Calendar c = Calendar.getInstance();
            c.setTime(createTime);
            c.add(Calendar.DAY_OF_MONTH, day);
            Date endDate = c.getTime();
            Date now = new Date();
            return now.after(endDate);
        }
        // 永久有效
        return false;
    }

    // --------------------------------------- 订单 ---------------------------------------

    /**
     * 订单列表
     */
    @ApiOperation(value = "订单列表", notes = "订单列表")
    @GetMapping(value = "/order/list")
    public Result<?> orderList(BaseOrder baseOrder,
                               @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                               @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                               HttpServletRequest req) {

        QueryWrapper<BaseOrder> queryWrapper = new QueryWrapper<>();
        // req.getParameterMap()被锁定无法删除元素，复制一份
        Map<String, String[]> pMap = new HashMap<>(req.getParameterMap());
//        // status条件不走框架自带判断
//        String[] statuses = pMap.remove("orderStatus");
//        String orderStatus = statuses == null || statuses.length == 0 ? null : statuses[0];
//        // status = 3时，只展示下架（售罄）的商品
//        if (orderStatus == null || "".equals(orderStatus)) {
//            baseOrder.setOrderStatus(null);
//            queryWrapper.ne("order_status", );
//        }
        String[] columns = pMap.get("column");
        String column = columns == null || columns.length == 0 ? null : columns[0];
        if (StringUtils.isEmpty(column) || "createTime".equals(column)) {
            // 没有排序条件时，默认创建时间倒序
            pMap.put("column", new String[]{"createTime"});
            pMap.put("order", new String[]{"desc"});
        }
        QueryGenerator.initQueryWrapper(queryWrapper, baseOrder, pMap);
        Page<BaseOrder> page = new Page<BaseOrder>(pageNo, pageSize);
        IPage<BaseOrder> pageList = baseOrderService.page(page, queryWrapper);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<BaseOrder> records = pageList.getRecords();
        List<Map<String, Object>> records1 = records.stream().map(o -> {
            Map<String, Object> m = ToolsUtils.objectToMap(o);
            if (StringUtils.isNotEmpty(o.getPayParamsStr())) {
                m.put("payParams", JSON.parse(o.getPayParamsStr()));
            }
            Date createTime = (Date) m.get("createTime");
            Date updateTime = (Date) m.get("updateTime");
            if (createTime != null) {
                m.put("createTime", sdf.format(createTime));
            }
            if (updateTime != null) {
                m.put("updateTime", sdf.format(updateTime));
            }
            return m;
        }).collect(Collectors.toList());
        IPage<Map<String, Object>> pageList1 = new PageDTO<>();
        BeanUtils.copyProperties(pageList, pageList1);
        pageList1.setRecords(records1);
        return Result.OK(pageList1);
    }

    /**
     * 订单详情
     */
    @ApiOperation(value = "订单详情", notes = "订单详情")
    @GetMapping(value = "/order/detail")
    public Result<?> orderDetail(@RequestParam("orderId") String orderId) {
        BaseOrder order = baseOrderService.getById(orderId);
        if (order == null) {
            return Result.error("未找到对应数据");
        }
        Map<String, Object> map = ToolsUtils.objectToMap(order);
        map.put("couponListJson", JSON.parse(order.getCouponListJsonStr()));
        map.put("commodityListJson", JSON.parse(order.getCommodityListJsonStr()));
        map.put("payParams", JSON.parse(order.getPayParamsStr()));
        return Result.OK(map);
    }

    // --------------------------------------- 股东中心 ---------------------------------------

    /**
     * 股东拓客卡列表
     */
    @ApiOperation(value = "股东拓客卡列表", notes = "股东拓客卡列表")
    @GetMapping(value = "/stock/vipList")
    public Result<?> getStockVipList(@RequestParam(value = "cardId", required = false) String cardId
            , @RequestParam("storeId") String storeId
            , @RequestParam("stockId") String stockId) {

        List<BaseMemberShareVip> list = baseMemberShareVipService.list(new QueryWrapper<BaseMemberShareVip>()
                .eq("store_id", storeId)
                .eq("stock_id", stockId)
                .gt("num", 0)
                .eq("card_type", "股东拓客卡")
                .like(StringUtils.isNotEmpty(cardId), "card_id", cardId));

        List<Map<String, Object>> result = new ArrayList<>();
        for (BaseMemberShareVip ele : list) {
            Map<String, Object> map = org.jeecg.modules.util.BeanUtils.bean2Map(ele);
            Map<String, Object> style = getStyle(ele.getStoreId(), String.valueOf(ele.getCardId()));

            map.put("style", style);
            result.add(map);
        }

        return Result.OK(result);
    }

//    /**
//     * 股东拓客卡-优惠卷
//     */
//    @GetMapping(value = "/stock/queryCouponList")
//    public Result<?> queryCouponList(
//            @RequestParam(name = "id", required = true) String id,
//            @RequestParam(name = "storeId", required = true) String storeId,
//            @RequestParam(name = "ticketName", required = false) String ticketName,
//            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
//            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
//
//        Map<String, Object> params = new HashMap<>();
//        params.put("storeId", storeId);
//        params.put("vipId", id);
//        params.put("ticketName", ticketName);
//        Page<CouponManagement> page = new Page<>(pageNo, pageSize);
//        // 注意这里id是关联表的id，num也取自关联表
//        IPage<CouponManagement> pageList = allVipcardService.queryCouponList(page, params);
//        return Result.OK(pageList);
//    }

    /**
     * 股本明细
     */
    @ApiOperation(value = "股本明细", notes = "股本明细")
    @GetMapping(value = "/stock/listStockBalanceRecord")
    public Result<?> listStockBalanceRecord(@RequestParam("stockId") String stockId,
                                            @RequestParam("storeId") String storeId,
                                            @RequestParam(name = "createTime", required = false) String createTime,
                                            @RequestParam(name = "name", required = false) String name,
                                            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {

        Page<Map<String, Object>> page = new Page<>(pageNo, pageSize);
        return Result.OK(stockManageService.listStockBalanceRecord(page, storeId, stockId, createTime, name));
    }

    /**
     * 分红明细
     */
    @ApiOperation(value = "分红明细", notes = "分红明细")
    @GetMapping(value = "/stock/listStockDividendRecord")
    public Result<?> listStockDividendRecord(@RequestParam("stockId") String stockId,
                                             @RequestParam("storeId") String storeId,
                                             @RequestParam(name = "createTime", required = false) String createTime,
                                             @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        List<Map<String, Object>> records = new ArrayList<>();
//TODO LukasLi真正分页
        List<String> highStock = getHighStock(storeId, stockId);
        if (highStock.size() > 0) {
            for (String id : highStock) {
                IPage<Map<String, Object>> page = stockManageService.listStockDividendRecord(storeId, id, createTime, pageNo, pageSize);
                List<Map<String, Object>> records1 = page.getRecords();
                for (Map<String, Object> m : records1) {
                    if (m.get("dividendMoney") != null) {
                        m.put("dividendMoney", ToolsUtils.formatNumber(m.get("dividendMoney")));
                    }
                    if (m.get("memberPhone") != null) {
                        String memberPhone = String.valueOf(m.get("memberPhone"));
                        m.put("memberPhone", memberPhone.substring(0, 3) + "****" + memberPhone.substring(7));
                    }
                    m.put("relation", "2");
                    records.add(m);
                }
            }
        }
        List<String> lowStock = getLowStock(storeId, stockId);
        if (lowStock.size() > 0) {
            for (String id : lowStock) {
                IPage<Map<String, Object>> page = stockManageService.listStockDividendRecord(storeId, id, createTime, pageNo, pageSize);
                List<Map<String, Object>> records1 = page.getRecords();
                for (Map<String, Object> m : records1) {
                    if (m.get("dividendMoney") != null) {
                        m.put("dividendMoney", ToolsUtils.formatNumber(m.get("dividendMoney")));
                    }
                    if (m.get("memberPhone") != null) {
                        String memberPhone = String.valueOf(m.get("memberPhone"));
                        m.put("memberPhone", memberPhone.substring(0, 3) + "****" + memberPhone.substring(7));
                    }
                    m.put("relation", "2");
                    records.add(m);
                }
            }
        }
        IPage<Map<String, Object>> page = stockManageService.listStockDividendRecord(storeId, stockId, createTime, pageNo, pageSize);
        List<Map<String, Object>> records1 = page.getRecords();
        for (Map<String, Object> m : records1) {
            if (m.get("dividendMoney") != null) {
                m.put("dividendMoney", ToolsUtils.formatNumber(m.get("dividendMoney")));
            }
            if (m.get("memberPhone") != null) {
                String memberPhone = String.valueOf(m.get("memberPhone"));
                m.put("memberPhone", memberPhone.substring(0, 3) + "****" + memberPhone.substring(7));
            }
            m.put("relation", "1");
            records.add(m);
        }
        page.setRecords(records);
        return Result.OK(page);
    }

    private List<String> getHighStock(String storeId, String stockId) {
        List<String> list = new ArrayList<>();
        StockManage stock = stockManageService.getById(stockId);
        if (stock != null) {
            String memberId = stock.getMemberId();
            if (memberId != null) {
                MemberManagement member = memberManagementService.getById(memberId);

                String stockId1 = member.getStockId();
                if (StringUtils.isEmpty(stockId1)) {
                    StockManage byId = stockManageService.getById(stockId1);
                    if (byId != null) {
                        list.add(stockId1);
                    }
                }
                String myStockId = member.getMyStockId();
                if (StringUtils.isEmpty(myStockId)) {
                    StockManage byId = stockManageService.getById(myStockId);
                    if (byId != null) {
                        list.add(myStockId);
                    }
                }
            }
        }

        return list;
    }

    private List<String> getLowStock(String storeId, String stockId) {
        List<String> list = new ArrayList<>();
        StockManage stock = stockManageService.getById(stockId);

        List<MemberManagement> members = memberManagementService.list(new QueryWrapper<MemberManagement>().eq("high_stock_id", stockId));

        for (MemberManagement member : members) {
            String myStockId = member.getMyStockId();
            String stockId1 = member.getStockId();


            if (StringUtils.isEmpty(stockId1)) {
                StockManage byId = stockManageService.getById(stockId1);
                if (byId != null) {
                    list.add(stockId1);
                }
            }
            if (StringUtils.isEmpty(myStockId)) {
                StockManage byId = stockManageService.getById(myStockId);
                if (byId != null) {
                    list.add(myStockId);
                }
            }
        }


        return list;
    }


    /**
     * 查询股东分红统计
     */
    @ApiOperation(value = "查询股东分红统计", notes = "查询股东分红统计")
    @GetMapping(value = "/stock/getStockDividendCount")
    public Result<StockDividendCount> getStockDividendCount(@RequestParam(name = "storeId", defaultValue = "") String storeId,
                                                            @RequestParam(name = "stockId", defaultValue = "") String stockId) {
        Result<StockDividendCount> result = new Result<>();
        StockManage stockManage = stockManageService.getById(stockId);
        Double dividendSum = stockManageService.getStockDividendSum(stockManage.getStoreId(), stockManage.getMemberId(), stockManage.getId());
        StockDividendCount stockDividendCount = stockManageService.getStockDividendCount(storeId, stockId);
        stockDividendCount.setTotalDividend(dividendSum);
        result.setSuccess(true);
        result.setResult(stockDividendCount);
        return result;
    }

    /**
     * 直接客源明细
     */
    @ApiOperation(value = "客源明细", notes = "客源明细")
    @GetMapping(value = "/stock/stockMemberList")
    public Result<?> queryPageList(MemberManagement memberManagement,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {

       // String stockId=req.getParameter("stockId");
      //  String storeId=req.getParameter("storeId");
//highStockId


        QueryWrapper<MemberManagement> queryWrapper = new QueryWrapper<>();

        QueryGenerator.initQueryWrapper(queryWrapper, memberManagement, req.getParameterMap());
       // queryWrapper.eq()

        Page<MemberManagement> page = new Page<>(pageNo, pageSize);
        IPage<MemberManagement> pageList = memberManagementService.page(page, queryWrapper);
        List<MemberManagement> records = pageList.getRecords();
        records.forEach(mm -> {
            StoreInfo store = storeInfoService.getById(mm.getStoreId());
            if (store != null) {
                mm.setBelongStore(store.getStoreName());
            }
            StockManage stock = stockManageService.getById(mm.getStockId());
            if (stock != null) {
                mm.setShareholders(stock.getStockName() + stock.getTel());
            }
            LevelSet level = levelSetService.getById(mm.getLevelId());
            if (level != null) {
                mm.setMemberLevel(level.getRankName());
            }
            if (mm.getPhone() != null) {
                String phone = mm.getPhone();
                mm.setPhone(phone.substring(0, 3) + "****" + phone.substring(7));
            }
        });
        return Result.OK(pageList);
    }

    /**
     * 间接客源明细
     */
    @ApiOperation(value = "间接客源明细", notes = "间接客源明细")
    @GetMapping(value = "/stock/stockIndiectMemberList")
    public Result<?> queryPageList2(MemberManagement memberManagement,
                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                    HttpServletRequest req) {

        QueryWrapper<MemberManagement> queryWrapper = new QueryWrapper<>();
        QueryGenerator.initQueryWrapper(queryWrapper, memberManagement, req.getParameterMap());
        Page<MemberManagement> page = new Page<>(pageNo, pageSize);
        IPage<MemberManagement> pageList = memberManagementService.page(page, queryWrapper);
        List<MemberManagement> records = pageList.getRecords();
        records.forEach(mm -> {
            StoreInfo store = storeInfoService.getById(mm.getStoreId());
            if (store != null) {
                mm.setBelongStore(store.getStoreName());
            }
            StockManage stock = stockManageService.getById(mm.getStockId());
            if (stock != null) {
                mm.setShareholders(stock.getStockName() + stock.getTel());
            }
            LevelSet level = levelSetService.getById(mm.getLevelId());
            if (level != null) {
                mm.setMemberLevel(level.getRankName());
            }
            if (mm.getPhone() != null) {
                String phone = mm.getPhone();
                mm.setPhone(phone.substring(0, 3) + "****" + phone.substring(7));
            }
        });
        return Result.OK(pageList);
    }

    /**
     * 申请提现
     *
     * @return
     */
    @AutoLog(value = "申请提现")
    @ApiOperation(value = "申请提现", notes = "申请提现")
    @RequestMapping(value = "/widthManagment/applyWithdrawal", method = RequestMethod.PUT)
    @Transactional(rollbackFor = Exception.class)
    public Result<?> applyWithdrawal(@RequestParam("stockId") String stockId,
                                     @RequestParam("storeId") String storeId,
                                     @RequestParam(value = "remark", required = false) String remark,
                                     @RequestParam("applyAmount") Double applyAmount) {

        StockManage stock = stockManageService.getById(stockId);
        if (stock == null) {
            return Result.error("股东不存在");
        }
        BigDecimal canWithdrawal = new BigDecimal(String.valueOf(stock.getCanWithdrawal()));
        BigDecimal applyAmountB = new BigDecimal(String.valueOf(applyAmount));
        if (canWithdrawal.compareTo(applyAmountB) < 0) {
            return Result.error("可提现余额不足");
        }
        stock.setCanWithdrawal(canWithdrawal.subtract(applyAmountB).doubleValue());
        stock.setUpdateBy("xcx");
        stockManageService.updateById(stock);

        WidthManagement widthManagement = new WidthManagement();
        widthManagement.setCreateBy("xcx");
        widthManagement.setStockId(stockId);
        widthManagement.setApplyAmount(applyAmount);
        widthManagement.setStatus("00");
        widthManagement.setRemark(remark);
        widthManagement.setStoreId(storeId);
        widthManagementService.save(widthManagement);
        // 模板消息
        try {
            String bossGzhOpenId = storeInfoService.getBossGzhOpenId(storeId);
            if (bossGzhOpenId == null) {
                log.info("发送提现申请审批通知模板推送失败，老板未绑定公众号");
            } else {
                StoreInfo store = storeInfoService.getById(storeId);
                if (store == null) {
                    log.info("发送提现申请审批通知模板推送失败，未查到店铺信息");
                } else {
                    String gzhAppId = store.getGzhAppId();
                    String gzhAppSecret = store.getGzhAppSecret();
                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                        log.info("发送提现申请审批通知模板推送失败，店铺未绑定公众号");
                    } else {
                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                        String result1 = HttpUtils.sendGet(url1);
                        JSONObject resultJson1 = JSON.parseObject(result1);
                        String errcode = resultJson1.getString("errcode");
                        if (errcode != null && !"0".equals(errcode)) {
                            log.info("发送提现申请审批通知模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                        } else {
                            String accessToken = resultJson1.getString("access_token");
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("提现申请审批通知", storeId);
                            String templateId = msgTemplate.getTemplateId();
                            util.withdrawalApplyApproveNotice(templateId, bossGzhOpenId, stock.getStockName(), String.valueOf(applyAmount), sdf.format(new Date()), store.getXcxAppId(), "", accessToken);
                            log.info("发送提现申请审批通知模板推送成功");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("发送提现申请审批通知模板推送失败，发生异常", e);
        }
        return Result.OK("申请成功!");
    }

    /**
     * 查询提现记录
     */
    @ApiOperation(value = "查询提现记录", notes = "查询提现记录")
    @GetMapping("/widthManagment/getWidthManagmentList")
    public Result<?> getWidthManagmentList(@RequestParam("storeId") String storeId, @RequestParam("stockId") String stockId) {

        List<WidthManagement> list = widthManagementService.list(new QueryWrapper<WidthManagement>()
                .eq("store_id", storeId)
                .eq("stock_id", stockId)
                .orderByDesc("create_time"));

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        List<Map<String, Object>> result = list.stream().map(wm -> {
            Map<String, Object> m = ToolsUtils.objectToMap(wm);
            StockManage stock = stockManageService.getById(wm.getStockId());
            if (stock != null) {
                m.put("stockName", stock.getStockName());
                m.put("tel", stock.getTel());
            }
            m.put("statusName", "00".equals(wm.getStatus()) ? "未审核" : "01".equals(wm.getStatus()) ? "通过" : "驳回");
            Date createTime = (Date) m.get("createTime");
            Date updateTime = (Date) m.get("updateTime");
            if (createTime != null) {
                m.put("createTime", sdf.format(createTime));
            }
            if (updateTime != null) {
                m.put("updateTime", sdf.format(updateTime));
            }
            return m;
        }).collect(Collectors.toList());
        return Result.OK(result);
    }

    /**
     * 查询可提现金额
     *
     * @param storeId
     * @param stockId
     * @return
     */
    @AutoLog(value = "查询可提现金额")
    @ApiOperation(value = "查询可提现金额", notes = "查询可提现金额")
    @GetMapping(value = "/widthManagment/getCanWithdrawalAmount")
    public Result<?> getCanWithdrawalAmount(@RequestParam("storeId") String storeId, @RequestParam("stockId") String stockId) {

        StockManage stock = stockManageService.getById(stockId);
        Map<String, Object> result = new HashMap<>();
        result.put("haveWithdrawal", stock.getHaveWithdrawal());
        result.put("canWithdrawal", stock.getCanWithdrawal());
        return Result.OK(result);
    }

    /**
     * 查询关注者列表
     *
     * @return
     */
    @AutoLog(value = "查询关注者列表")
    @ApiOperation(value = "查询关注者列表", notes = "查询关注者列表")
    @GetMapping(value = "/getOfficialAccountUser")
    public Result<?> getOfficialAccountUser(HttpServletRequest req) {
        OfficialAccountToken officialAccountToken = officialAccountTokenService.getToken("wx42ecd92353c89e9f", "955609cb9cb5d3ee036caaed2f883277");
        if (officialAccountToken != null) {
            List<String> listOpenId = officialAccountUserService.getUserOpenId(officialAccountToken.getToken(), "");
            if (listOpenId != null) {
                if (listOpenId.size() > 0) {
                    List<OfficialAccountUser> listOfficialAccountUser = officialAccountUserService.getUserInfo(listOpenId);
                }
            }
        }
        return Result.OK();
    }

    /**
     * 获取关注公众号url
     */
    @ApiOperation(value = "获取关注公众号url", notes = "获取关注公众号url")
    @GetMapping(value = "/getGzUrl")
    public Result<?> getGzUrl(@RequestParam("storeId") String storeId) {
        StoreInfo storeInfo = storeInfoService.getById(storeId);
        if (storeInfo == null) {
            return Result.error("未找到对应店铺");
        }
        Map<String, Object> map = ToolsUtils.objectToMap(storeInfo);
        map.put("gzUrl", storeInfo.getGzUrl());
        return Result.OK(map);
    }

    /**
     * 测试
     *
     * @return
     */
    @AutoLog(value = "测试")
    @ApiOperation(value = "测试", notes = "测试")
    @GetMapping(value = "/jsonTest")
    public Result<?> jsonTest(HttpServletRequest req) {
        String jsonStr = "{\"template_list\":[{\"primary_industry\":\"\",\"deputy_industry\":\"\",\"template_id\":\"AtMkwXFuqyYRkdkmVSR1YSXW-5xxU6vA-AUM9wMmpyI\",\"title\":\"订阅模板消息\",\"content\":\"{{content.DATA}}\",\"example\":\"\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"gG0y_G8jzhhsEt1IyabnqUrpg_N3SZxcwdT5helFi9M\",\"title\":\"会员等级变更通知\",\"content\":\"{{first.DATA}}\\n原先等级：{{keyword1.DATA}}\\n当前等级：{{keyword2.DATA}}\\n折扣：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"恭喜您在“Seven-E”的会员等级升级啦\\r\\n原先等级：白银会员\\r\\n当前等级：黄金会员\\r\\n折扣：8折\\r\\n详情\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"envPcc6nCpfVbpQ6qMfaIeMh1KnN12ZkOSdaG1u_0GM\",\"title\":\"消费提醒\",\"content\":\"{{first.DATA}}\\n消费日期：{{keyword1.DATA}}\\n消费金额：{{keyword2.DATA}}\\n消费店铺：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"尊敬的用户，您的车牌号苏E12345,消费信息如下，\\r\\n消费日期：2014-10-20 14：30\\r\\n消费金额：100元\\r\\n消费店铺：苏州众星汽车修理厂\\r\\n感谢您的使用，点击查看详细信息\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"V2dXYxUd0BKCZFyd2vGV0iOzEufJDc-Q02WMCpUhicA\",\"title\":\"退款通知\",\"content\":\"{{first.DATA}}\\n商户名称：{{keyword1.DATA}}\\n退款金额：{{keyword2.DATA}}\\n退款订单号：{{keyword3.DATA}}\\n退款时间：{{keyword4.DATA}}\\n{{remark.DATA}}\",\"example\":\"您有一笔订单退款成功\\r\\n商户名称：182.00元\\r\\n退款金额：桂馨媛店\\r\\n退款订单号：100925099\\r\\n退款时间：2018-06-23 10:23:37\\r\\n前往处理\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"cctIRpfGprwvfWiTb5cDTTMIm6h4m1yokc3mmmsAwBo\",\"title\":\"成为会员通知\",\"content\":\"{{first.DATA}}\\n姓名：{{keyword1.DATA}}\\n手机号：{{keyword2.DATA}}\\n会员卡卡号：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"尊敬的用户您好：\\r\\n姓名：陈丽\\r\\n手机号：13389990003\\r\\n会员卡卡号：10099889993\\r\\n恭喜您成为本站会员，感谢您的使用！\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"qbt53Rt64Pe6NYMjWdeD6hTX_ZqQCUb6-cDiF_hB_J0\",\"title\":\"订单核销成功提醒\",\"content\":\"{{first.DATA}}\\n订单编号：{{keyword1.DATA}}\\n商品名称：{{keyword2.DATA}}\\n店铺名称：{{keyword3.DATA}}\\n核销时间：{{keyword4.DATA}}\\n{{remark.DATA}}\",\"example\":\"尊敬的会员，您的订单已成功核销。\\r\\n订单编号：413686029\\r\\n商品名称：猪扒包外脆内软，鲜嫩多汁！外有小食、饮品加持！\\r\\n店铺名称：鲜果乐\\r\\n核销时间：2021-06-10 17:41:23\\r\\n感谢您的使用！\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"yvbkfXXxExidTgsEyHnINMmfmed2mEusqzEo0YdieJI\",\"title\":\"待反馈任务提醒\",\"content\":\"{{first.DATA}}\\n通知内容：{{keyword1.DATA}}\\n通知时间：{{keyword2.DATA}}\\n{{remark.DATA}}\",\"example\":\"您好，小新，您有以下待反馈任务未结束\\r\\n通知内容：您目前共有6项任务未结束，其中2项任务已延期，请及时跟进反馈\\r\\n通知时间：2014年8月3日 17:00\\r\\n可点击详情查看任务明细列表及快捷反馈\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"RzuFeaitTe4CaKgTY7Y-6et-tl6kf_StP37b1JdegiE\",\"title\":\"提现成功通知\",\"content\":\"{{first.DATA}}\\n提现金额：{{keyword1.DATA}}\\n时间：{{keyword2.DATA}}\\n{{remark.DATA}}\",\"example\":\"你好，你已提现成功\\r\\n提现金额：200\\r\\n时间：2015年12月17日 18:36\\r\\n感谢你的使用\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"2WCWBOj4t5kOHfvBOfNgNpxp-upqEfU_owuYQVWCH0Q\",\"title\":\"提现驳回通知\",\"content\":\"{{first.DATA}}\\n提现用户：{{keyword1.DATA}}\\n提现金额：{{keyword2.DATA}}\\n处理时间：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"您的提现申请已被驳回\\r\\n提现用户：张三\\r\\n提现金额：1000元\\r\\n处理时间：2014年7月21日 18:36\\r\\n上级商家驳回您提现申请，请重新提交申请！\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"79-b8hgtBD_Bw0TCaDU3cWMz-2Y6SYHwOdcxeDdzmZ0\",\"title\":\"成为合伙人提醒\",\"content\":\"{{first.DATA}}\\n合伙人：{{keyword1.DATA}}\\n加入时间：{{keyword2.DATA}}\\n{{remark.DATA}}\",\"example\":\"恭喜您成功成为合伙人\\r\\n合伙人：小明\\r\\n加入时间：2014年7月21日 18:36\\r\\n感谢您的支持\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"rB7eizwCsBFyrsYq02vfdxXqfblSg50JKiF-iRGYRtk\",\"title\":\"推荐会员成功提醒\",\"content\":\"{{first.DATA}}\\n会员账号：{{keyword1.DATA}}\\n时间：{{keyword2.DATA}}\\n{{remark.DATA}}\",\"example\":\"您好，【JKLHLOO】已通过扫描您的专属二维码被推荐成为会员。\\r\\n会员账号：JKLHLOO\\r\\n时间：2014年7月21日 18:36\\r\\n推荐关注积分已打入您的会员账户，感谢您的推荐。\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"hCZmKI4OQ7DwV1L8ch7f17Y4A6T06gtstt4Fdhs8N1I\",\"title\":\"用户退款通知\",\"content\":\"{{first.DATA}}\\n退款人：{{keyword1.DATA}}\\n退款原因：{{keyword2.DATA}}\\n退款金额：{{keyword3.DATA}}\\n退款时间：{{keyword4.DATA}}\\n{{remark.DATA}}\",\"example\":\"尊敬的商户您好,您的用户有一笔新的退款\\r\\n退款人：许文强\\r\\n退款原因：充电桩爆炸了\\r\\n退款金额：800.00\\r\\n退款时间：2021-08-12 13:34\\r\\n点击登录商户后台，查看详情\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"rf0KJfKQJi81LqKq5YLSGtuqTHXGFh6vTWt43BMwCs8\",\"title\":\"订单分红提醒\",\"content\":\"{{first.DATA}}\\n本单分红：{{keyword1.DATA}}\\n累计分红：{{keyword2.DATA}}\\n下单时间：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"你好！你代理的店家已下单\\r\\n本单分红：2.00元\\r\\n累计分红：50.00元\\r\\n下单时间：2014年7月21日 18:36\\r\\n感谢你的参与\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"ZryZ4c0hhh2UKQQvVxIgynnKe_nqVKlVMZnmx2I8jAM\",\"title\":\"提现申请审批通知\",\"content\":\"{{first.DATA}}\\n申请人：{{keyword1.DATA}}\\n提现金额：{{keyword2.DATA}}\\n申请时间：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"待处理\\r\\n申请人：张三\\r\\n提现金额：200\\r\\n申请时间：2021-1-30\\r\\n请尽快处理\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"p11rOYJl3qPtiODk_idd6q_OX0WSXbduCpvIKWQKD0Y\",\"title\":\"新增成员提醒\",\"content\":\"{{first.DATA}}\\n新增成员：{{keyword1.DATA}}\\n加入时间：{{keyword2.DATA}}\\n邀请人：{{keyword3.DATA}}\\n{{remark.DATA}}\",\"example\":\"小王加入了王府\\r\\n新增成员：小王\\r\\n加入时间：2018年3月22日 18:30\\r\\n邀请人：老王\\r\\n快去看看吧。\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"EbEctj-hWhf138OY-fQi0taWPttj1uGLEHRR7kCqULc\",\"title\":\"库存不足提醒\",\"content\":\"{{first.DATA}}\\n剩余库存：{{keyword1.DATA}}\\n时间：{{keyword2.DATA}}\\n{{remark.DATA}}\",\"example\":\"产品1111111\\r\\n剩余库存：10\\r\\n时间：2016-06-22 13\\r\\n感谢你的使用。\"},{\"primary_industry\":\"IT科技\",\"deputy_industry\":\"IT软件与服务\",\"template_id\":\"wYwKE2TGRPCRwnsEDgg7x2LqrHsU8KzLaB7yhdY0pYo\",\"title\":\"商家自提订单提醒\",\"content\":\"{{first.DATA}}\\n订单编号：{{keyword1.DATA}}\\n下单时间：{{keyword2.DATA}}\\n下单人：{{keyword3.DATA}}\\n下单人手机号：{{keyword4.DATA}}\\n商品ID：{{keyword5.DATA}}\\n{{remark.DATA}}\",\"example\":\"您有新的自提订单待用户提货，请及时关注商品库存情况\\r\\n订单编号：MA0012101221\\r\\n下单时间：2021-01-22 12:58:23\\r\\n下单人：张三\\r\\n下单人手机号：15200000000\\r\\n商品ID：15\\r\\n若商品库存不足，请及时致电下单人协商，避免用户空跑，引起客诉！\"}]}";
        Map<String, Object> map = (Map) JSON.parse(jsonStr);
        List<Map> listMsgTemplateEntity = (List<Map>) JSON.parse(map.get("template_list").toString());
        String aa = listMsgTemplateEntity.get(1).get("template_id").toString();
        String bb = listMsgTemplateEntity.get(1).get("content").toString();
        System.out.println(aa);
        System.out.println(bb);
//        Map map2 = (Map)(JSON.parse(aa));
//        MsgTemplateEntity msgTemplateEntity = (MsgTemplateEntity)(JSON.parse(aa));
//        //List<Map<String,Object>> msgTemplateEntity =(List<Map<String,Object>>)listMsgTemplateEntity.get(1);
//        System.out.println((((MsgTemplateEntity)listMsgTemplateEntity.get(1))).getTitle().toString());
        return Result.OK();
    }

    /**
     * 获取地理位置显示标识
     *
     * @return
     */
    @AutoLog(value = "获取地理位置显示标识")
    @ApiOperation(value = "获取地理位置显示标识", notes = "获取地理位置显示标识")
    @GetMapping(value = "/getLocFlag")
    public Result<?> getLocFlag(HttpServletRequest req) {
        return Result.OK("0");
    }

    /**
     * <-预约->
     */
    @AutoLog(value = "预约分组")
    @ApiOperation(value = "0429预约分组", notes = "预约分组")
    @GetMapping(value = "/prebookGroup")
    public Result<?> prebookGroup(@RequestParam(value = "storeId", required = true, defaultValue = "-1") String storeId) {
        System.out.println("Lukasli:" + appService);
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }
        List<StoreProjectGroup> list = storeProjectGroupService.list(
                new QueryWrapper<StoreProjectGroup>().eq("store_id", storeId).orderByAsc("sort_no")
        );

        return Result.ok(list);
    }

    /**
     * 根据分组获得下面预约的记录条数
     *
     * @param groupId
     * @return
     */

    @AutoLog(value = "预约分组预约的明细")
    @ApiOperation(value = "0429预约分组预约的明细", notes = "预约分组预约的明细")
    @GetMapping(value = "/prebookGroupDetail")
    public Result<?> fectchProject4Group(
            @RequestParam(value = "storeId", required = true, defaultValue = "") String storeId,
            @RequestParam(value = "groupId", required = true, defaultValue = "") String groupId
            // @RequestParam(value = "groupId", required = true, defaultValue = "") String groupId
    ) {
        if (StringUtils.isBlank(groupId)) {
            return Result.error("参数不足");
        }
        if (groupId.equals("0")) {
            List<StoreProject> list = appService.listStoreProjects(storeId);

            List<Map> result = new ArrayList<>();
            for (StoreProject p : list) {
                Map map = new HashMap();
                map.put("projectId", p.getId());
                map.put("projectName", p.getName());
                map.put("img", p.getImg());
                List<ReserveRecord> records = reserveRecordService.list(new QueryWrapper<ReserveRecord>().eq("store_id", storeId).eq("project_id", p.getId())
                                //.eq("status", "0")
                        //.or((i -> i.eq("status", "1"))
                        );
                map.put("count", records.size());
                result.add(map);
            }

            return Result.ok(result);
        } else {
            List<StoreProject> list = storeProjectService.list(new QueryWrapper<StoreProject>().eq("group_id", groupId)//.eq("is_show", "1")
                    .eq("is_del", "N")
                    .orderByAsc("sort_no"));
            List<Map> result = new ArrayList<>();
            for (StoreProject p : list) {
                Map map = new HashMap();
                map.put("projectId", p.getId());
                map.put("projectName", p.getName());
                map.put("img", p.getImg());
                List<ReserveRecord> records = reserveRecordService.list(new QueryWrapper<ReserveRecord>().eq("store_id", storeId).eq("project_id", p.getId()));
                map.put("count", records.size());
                result.add(map);
            }

            return Result.ok(result);
        }
    }

    @AutoLog(value = "某技师某天是否有时间")
    @ApiOperation(value = "04251某技师某天是否有时间", notes = "04252某技师某天是否有时间")

    @GetMapping(value = "/prebookTime")
    public Result<?> prebookTime(@RequestParam(value = "storeId", required = true, defaultValue = "-1") String storeId,
                                 @RequestParam(value = "projectId", required = true, defaultValue = "-1") String projectId,
                                 @RequestParam(value = "day", required = false, defaultValue = "") String day,
                                 @RequestParam(value = "employeeId", defaultValue = "") String employeeId) {
        /*
        /app/prebookTime?storeId=1551093550018179074&xzDay=2023-5-3&xzMem=0&memberId=1643998973938798593
         */
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }

        StoreProject project = storeProjectService.getById(projectId);
        if (project == null) {
            return Result.error("没有此项目");
        }

        if (!org.jeecg.modules.util.StringUtils.isBlank(employeeId)) {
            StoreEmplee employee = storeEmpleeService.getById(employeeId);
            if (employee == null) {
                return Result.error("没有此技师");
            }
        }


        LocalDate localDate = DateUtils.toLocalDate(day, "yyyy/M/d");

        LocalDate today = LocalDate.now();
        List<Period> list = generateList(store.getBusinessStart(), store.getBusinessEnd());
        Map<Integer, Period> map = new HashMap<>();
        for (Period p : list) {
            map.put(p.getStartHours(), p);
        }

        if (localDate.isAfter(today)) {
            //day是以后的话，看是否有预约记录

            for (Period p : list) {
                p.setStatus("1");
            }


            if (!org.jeecg.modules.util.StringUtils.isBlank(employeeId)) {
                List<ReserveRecord> reserveRecords = appService.listByEmployeeDate(storeId, projectId, localDate, employeeId);
                for (ReserveRecord r : reserveRecords) {
                    int startHours = getStartHours(r.getReserveTime());
                    Period period = map.get(startHours);
                    period.setStatus("0");
                }
            }
        } else if (localDate.isEqual(today)) {
            //day 是今天，当时的两个小时前不可用

            LocalTime now = LocalTime.now();
            int hour = now.getHour();


            for (Period p : list) {
                if (p.getStartHours() < hour + store.getPrebookHours()) {
                    p.setStatus("0");
                } else {
                    p.setStatus("1");
                }
            }

            if (!org.jeecg.modules.util.StringUtils.isBlank(employeeId)) {
                List<ReserveRecord> reserveRecords = appService.listByEmployeeDate(storeId, projectId, localDate, employeeId);
                for (ReserveRecord r : reserveRecords) {
                    int startHours = getStartHours(r.getReserveTime());
                    Period period = map.get(startHours);
                    period.setStatus("0");
                }
            }

        } else {
            for (Period p : list) {
                p.setStatus("0");
            }
        }

        return Result.OK(list);
    }

    private int getStartHours(String rTime) {
        if (rTime == null) {
            return 0;
        }
        String[] split = rTime.split(":");
        if (split.length == 1 || split.length == 2 || split.length == 3) {
            return Integer.valueOf(split[0]);
        }

        return 0;
    }

    private List<Period> generateList(Date businessStart, Date businessEnd) {
        List<Period> result = new ArrayList<>();

        int startHours = businessStart.getHours();
        int endHours = businessEnd.getHours();
        int flag = 0;
        if (businessEnd.getMinutes() > 5) {
            flag = 1;
        }
        for (int i = startHours; i <= endHours - 1 - flag; i++) {
            result.add(PeriodFactory.newPeriod(i));
        }

        return result;
    }

    @AutoLog(value = "某技师某天是否有时间")
    @ApiOperation(value = "0427某技师某天是否有时间", notes = "某技师某天是否有时间")
    @GetMapping(value = "/prebookSave")
    public Result<?> prebookSave(
            @RequestParam(value = "storeId", required = true, defaultValue = "-1") String storeId,
            @RequestParam(value = "projectId", required = true, defaultValue = "-1") String projectId,
            @RequestParam(value = "day", required = true, defaultValue = "") String day,
            @RequestParam(value = "yuyueTime", required = true, defaultValue = "") String yuyueTime,
            @RequestParam(value = "employeeId", defaultValue = "") String employeeId,
            @RequestParam(value = "memberId", required = true, defaultValue = "") String memberId) {
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }

        StoreProject project = storeProjectService.getById(projectId);
        if (project == null) {
            return Result.error("没有此项目");
        }

        MemberManagement member = memberManagementService.getById(memberId);
        if (member == null) {
            return Result.error("没有会员");
        }
        String reserveTime = yuyueTime;
        try {
            reserveTime = URLDecoder.decode(yuyueTime, "UTF-8");
        } catch (Exception e) {
            reserveTime = yuyueTime;
        }
        if (!org.jeecg.modules.util.StringUtils.isBlank(employeeId)) {
            StoreEmplee employee = storeEmpleeService.getById(employeeId);
            if (employee == null) {
                return Result.error("没有此技师");
            }
            List<ReserveRecord> list = reserveRecordService.list(new QueryWrapper<ReserveRecord>().eq("store_id", storeId).eq("member_id", memberId).eq("order_date", day).eq("reserve_time", reserveTime));
            int counter = 0;
            for (ReserveRecord r : list) {
                if (r.getStatus().equals("1") || r.getStatus().equals("0")) {
                    counter++;
                }
            }
            if (counter > 0) {
                return Result.error("此会员已经预定了此时段!");
            }
        }


        LocalDate localDate = DateUtils.toLocalDate(day, "yyyy/M/d");

        ReserveRecord reserveRecord = new ReserveRecord();
        reserveRecord.setOrderNo(ToolsUtils.getBillNo("YY"));
        reserveRecord.setStoreId(storeId);
        reserveRecord.setProjectId(projectId);
        reserveRecord.setStaffId(employeeId);
        reserveRecord.setStatus("0");
        reserveRecord.setMemberId(memberId);

        reserveRecord.setOrderDate(localDate);
        reserveRecord.setReserveTime(reserveTime);
        reserveRecord.setOrderTime(LocalTime.now());


        if (member != null && !isBlank(member.getPhone())) {
            reserveRecord.setMemberName(member.getName());
            reserveRecord.setCellphone(member.getPhone());
        }
        if (reserveRecord.getPrebookTime() == null) {
            int startHours = getStartHours(reserveRecord.getReserveTime());
            LocalDateTime of = LocalDateTime.of(reserveRecord.getOrderDate(), LocalTime.of(startHours, 0));

            reserveRecord.setPrebookTime(DateUtils.local2util(of));
        }
        reserveRecordService.save(reserveRecord);


        // 模板消息
        try {
            String gzhOpenId = member.getGzhOpenId();
            if (gzhOpenId == null) {
                log.info("发送成为股东会员模板推送失败，股东未绑定公众号");
            } else {
                if (store == null) {
                    log.info("发送成为股东会员模板推送失败，未查到店铺信息");
                } else {
                    String bossGzhOpenId = storeInfoService.getBossGzhOpenId(store.getId());
                    String gzhAppId = store.getGzhAppId();
                    String gzhAppSecret = store.getGzhAppSecret();
                    if (StringUtils.isEmpty(gzhAppId) || StringUtils.isEmpty(gzhAppSecret)) {
                        log.info("发送成为股东会员模板推送失败，店铺未绑定公众号");
                    } else {
                        String url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + gzhAppId + "&secret=" + gzhAppSecret;
                        String result1 = HttpUtils.sendGet(url1);
                        JSONObject resultJson1 = JSON.parseObject(result1);
                        String errcode = resultJson1.getString("errcode");
                        if (errcode != null && !"0".equals(errcode)) {
                            log.info("发送成为股东会员模板推送失败，获取accessToken返回值异常，错误码：{}", errcode);
                        } else {
                            String accessToken = resultJson1.getString("access_token");
                            String memberPhone = member.getPhone();
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 HH:mm");
                            MsgTemplate msgTemplate = msgTemplateListService.getByTitle("推荐会员成功提醒", store.getId());
                            String templateId = msgTemplate.getTemplateId();
                            util.recommendMemberSuccessNotice(templateId, gzhOpenId, memberPhone.substring(0, 3) + "****" + memberPhone.substring(7), sdf.format(new Date()), store.getXcxAppId(), "user/share/tourist", accessToken);


                            log.info("发送成为股东会员模板推送成功");
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("发送成为股东会员模板推送失败，发生异常", e);
        }



        return Result.OK("");
    }

    @AutoLog(value = "预约列表")
    @ApiOperation(value = "0428预约列表", notes = "预约列表")
    @GetMapping(value = "/prebooklist")
    public Result<?> prebook(@RequestParam(value = "storeId", required = true, defaultValue = "-1") String storeId,
                             @RequestParam(value = "projectId", required = true, defaultValue = "-1") String projectId,
                             @RequestParam(value = "startDay", required = false, defaultValue = "null") Date startDay,
                             @RequestParam(value = "endDay", required = false, defaultValue = "null") Date endDay,
                             @RequestParam(value = "employeeId", defaultValue = "0") String employeeId) {
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }


        StoreProject project = storeProjectService.getById(projectId);
        if (project == null) {
            return Result.error("没有此项目");
        }


        StoreEmplee employee = storeEmpleeService.getById(employeeId);
        if (employee == null) {
            return Result.error("没有此技师");
        }


        List<ReserveRecord> reserveRecords = null;// appService.listByEmployeeDate(storeId, projectId, startDay, endDay, employeeId);

        return Result.ok(reserveRecords);
    }

    @AutoLog(value = "预约详情")
    @ApiOperation(value = "0429预约详情", notes = "预约详情")
    @GetMapping(value = "/prebookDetail")
    public Result<?> prebookDetail(@RequestBody Map<String, Object> map) {
        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String detailId = map.get("detailId") == null ? null : String.valueOf(map.get("detailId"));

        StoreInfo store = storeInfoService.getById(storeId);


        if (store == null) {
            return Result.error("没有店铺信息");
        }


        ReserveRecord r = appService.queryReserveRecordById(groupId);

        return Result.ok(r);
    }

    @AutoLog(value = "服务人员列表")
    @ApiOperation(value = "0429服务人员列表", notes = "技师列表")
    @GetMapping(value = "/listEmployee")
    public Result<?> listEmployee(@RequestParam(value = "storeId", required = false, defaultValue = "") String storeId,
                                  @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                  @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                  HttpServletRequest req) {


        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }

        QueryWrapper<StoreEmplee> queryWrapper = QueryGenerator.initQueryWrapper(new StoreEmplee(), req.getParameterMap());
        queryWrapper.eq("store_id", storeId).orderByAsc("seq_no");
        Page<StoreEmplee> page = new Page<StoreEmplee>(pageNo, pageSize);
        IPage<StoreEmplee> pageList = storeEmpleeService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    @AutoLog(value = "搜索项目")
    @ApiOperation(value = "0429搜索项目", notes = "搜索项目")
    @PostMapping(value = "/searchProjectByName")
    public Result<?> searchProjectByName(@RequestBody Map<String, Object> map, HttpServletRequest req) {

        String groupId = map.get("groupId") == null ? null : String.valueOf(map.get("groupId"));
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String name = map.get("keyword") == null ? null : String.valueOf(map.get("keyword"));
        Integer pageNo = map.get("pageNo") == null ? 1 : Integer.valueOf(map.get("pageNo").toString());
        Integer pageSize = map.get("pageSize") == null ? 10 : Integer.valueOf(map.get("pageSize").toString());

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }
        StoreProject storeProject = new StoreProject();
        QueryWrapper<StoreProject> queryWrapper = QueryGenerator.initQueryWrapper(storeProject, req.getParameterMap());


        if (!isBlank(storeId)) {
            queryWrapper.eq("store_id", storeId);
        }


        queryWrapper.eq("is_show", "1");
        queryWrapper.like(name != null, "name", name);


        List<StoreProject> list1 = storeProjectService.list(new QueryWrapper<StoreProject>().eq("store_id", storeId).eq("is_del", "N").like(name != null, "name", name));
        for (StoreProject p : list1) {
            List<ReserveRecord> list = reserveRecordService.list(new QueryWrapper<ReserveRecord>()
                    .eq("project_id", p.getId())
                    .eq("store_id", storeId));
            p.setCreateBy(String.valueOf(list.size()));
        }

        return Result.OK(list1);

    }
    /** <-预约->  */
    /**
     * <-会员中心->
     */

    @AutoLog(value = "预约列表(会员中心)")
    @ApiOperation(value = "0430预约列表(会员中心)", notes = "预约列表(会员中心)")
    @PostMapping(value = "/prebookList4Member")
    public Result<?> prebookList4Member(//
                                        @RequestBody Map<String, Object> map, HttpServletRequest req) {


        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String status = map.get("orderStatus") == null ? null : String.valueOf(map.get("orderStatus"));
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }

        List<ReserveRecord> list = reserveRecordService.list(new QueryWrapper<ReserveRecord>().eq("store_id", storeId).eq("member_id", memberId).eq("status", status).orderByDesc("create_time"));

// 3种类型分组
        List<Map> result = new ArrayList<>();
        for (ReserveRecord r : list) {
            Map<String, Object> rMap = org.jeecg.modules.util.BeanUtils.bean2Map(r);

            String projectId = r.getProjectId();
            StoreProject project = storeProjectService.getById(projectId);
            if (project != null) {
                rMap.put("projectName", project.getName());
            } else {
                rMap.put("projectName", "项目被删除");
            }

            if (r.getStaffId() == null) {
                rMap.put("staffName", "到店指派");
            } else {
                StoreEmplee emplee = storeEmpleeService.getById(r.getStaffId());
                if (emplee == null) {
                    rMap.put("staffName", "到店指派");
                } else {
                    rMap.put("staffName", emplee.getName());
                }
            }

            rMap.put("yuyueDateTime", DateUtils.format(r.getOrderDate(), "yyyy-MM-dd") + " " + r.getReserveTime());
            result.add(rMap);
        }

        return Result.ok(result);
    }

    @AutoLog(value = "改变状态")
    @ApiOperation(value = "0430改变状态", notes = "改变状态")
    @GetMapping(value = "/changeStatus")
    public Result<?> changeStatus(@RequestParam(value = "recordId", required = true, defaultValue = "") String recordId,
                                  @RequestParam(value = "status", required = true, defaultValue = "") String status
    ) {
        ReserveRecord record = reserveRecordService.getById(recordId);
        record.setStatus(status);
        reserveRecordService.updateById(record);

        return Result.ok("");
    }

    @AutoLog(value = "流水明细")
    @ApiOperation(value = "0430流水明细", notes = "流水明细")
    @GetMapping(value = "/accountDetail")
    public Result<?> accountDetail(@RequestParam(value = "storeId", required = true, defaultValue = "") String storeId,
                                   @RequestParam(value = "memberId", required = true, defaultValue = "") String memberId,
                                   @RequestParam(value = "orderStatus", required = true, defaultValue = "") String orderStatus
    ) {
        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }

        if ("0".equals(orderStatus)) {
//消费
            QueryWrapper<BaseOrder> wrapper = new QueryWrapper<BaseOrder>().eq("member_id", memberId).eq("store_id", storeId).eq("order_status", "1");
            wrapper.orderByDesc("create_time");
            List<BaseOrder> orders = baseOrderService.list(wrapper);
            return Result.ok(orders);
        } else if ("1".equals(orderStatus)) {
            //充值
            QueryWrapper<BasePayOrder> wrapper = new QueryWrapper<BasePayOrder>().eq("member_id", memberId).eq("store_id", storeId);
            wrapper.orderByDesc("create_time");
            List<BasePayOrder> payOrders = basePayOrderService.list(wrapper);
            List<BasePayOrder> result = new ArrayList<>();
            for (BasePayOrder order : payOrders) {
                if (order.getPayTime() != null) {
                    result.add(order);
                }
            }
            return Result.ok(result);


        } else if ("2".equals(orderStatus)) {
            //退款
            QueryWrapper<BaseOrder> wrapper = new QueryWrapper<BaseOrder>().eq("member_id", memberId).eq("store_id", storeId).eq("order_status", "2");
            wrapper.orderByDesc("create_time");
            List<BaseOrder> orders = baseOrderService.list(wrapper);

            return Result.ok(orders);
        }

        return Result.ok();
    }

    /**
     * 充值
     * 参数：*type(充值类型：会员余额充值/股本余额充值), *memberId(会员id), *amount(充值金额), staffId(提成归属员工id), *payType(支付方式：扫码支付、现金支付、微信记账、支付宝记账)
     */

    @AutoLog(value = "保存订单")
    @ApiOperation(value = "0508充值", notes = "充值")
    @PostMapping(value = "/savePayOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> savePayOrder(@RequestBody Map<String, Object> map) {
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String saobeiType = map.get("saobeiType") == null ? null : String.valueOf(map.get("saobeiType"));
        String payName = map.get("payName") == null ? null : String.valueOf(map.get("payName"));
        String realAmount = map.get("realAmount") == null ? null : String.valueOf(map.get("realAmount"));
        String remark = map.get("remark") == null ? "扫呗扫码充值" : String.valueOf(map.get("remark"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(remark)) {
            log.info("savePayOrder:参数不全");
            return Result.error("参数不全");
        }

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }
        MemberManagement member = memberManagementService.getById(memberId);

        if (member == null) {
            return Result.error("没有会员信息");
        }
        BasePayOrder payOrder = new BasePayOrder();


        payOrder.setStoreId(storeId);
        payOrder.setOrderCode(ToolsUtils.getBillNo("MR"));
        payOrder.setMemberId(memberId);
        payOrder.setMemberName(member.getName());
        payOrder.setMemberPhone(member.getPhone());
        payOrder.setStockId(member.getMyStockId());
        payOrder.setRechargeAmount(Double.valueOf(realAmount));
        payOrder.setName(payName);
        payOrder.setRechargeType("扫呗扫码支付");
        payOrder.setPayType("扫呗扫码支付");


        boolean save = basePayOrderService.save(payOrder);
        if (!save) {
            Result.error("保存支付订单失败");
        }


        String xcxAppId = store.getXcxAppId();
        if (StringUtils.isEmpty(xcxAppId)) {
            log.info("saveOrder:店铺还未绑定小程序");
            return Result.error("店铺还未绑定小程序");
        }
        String saobeiMerchantNo = store.getSaobeiMerchantNo();
        String saobeiTerminalId = store.getSaobeiTerminalId();
        String saobeiAccessToken = store.getSaobeiAccessToken();
        if (StringUtils.isEmpty(saobeiMerchantNo) || StringUtils.isEmpty(saobeiTerminalId) || StringUtils.isEmpty(saobeiAccessToken)) {
            log.info("saveOrder:店铺还未绑定支付");
            return Result.error("店铺还未绑定支付");
        }

        MemberManagement mm = memberManagementService.getById(memberId);
        String xcxOpenId = mm.getXcxOpenId();
        if (StringUtils.isEmpty(xcxOpenId)) {
            log.info("saveOrder:会员还未绑定小程序");
            return Result.error("会员还未绑定小程序");
        }
        BigDecimal realAmountDecimal = new BigDecimal(realAmount);
        String totalFee = String.valueOf(realAmountDecimal.multiply(new BigDecimal("100")).intValue());

        SaobeiMiniPayResponse minipayResponse = Saobei.minipay(saobeiAccessToken, saobeiMerchantNo, saobeiTerminalId, xcxAppId, xcxOpenId, "小程序订单", payOrder.getId(), totalFee);
        if ("01".equals(minipayResponse.getResult_code())) {
            SaobeiOrderRecord saobeiOrderRecord = new SaobeiOrderRecord();
            saobeiOrderRecord.setType(saobeiType);
            saobeiOrderRecord.setOutTradeNo(minipayResponse.getOut_trade_no());
            saobeiOrderRecord.setTerminalTrace(payOrder.getId());
            saobeiOrderRecord.setTotalFee(totalFee);
            saobeiOrderRecord.setStoreId(storeId);
            saobeiOrderRecord.setCreateBy("xcx");
            saobeiOrderRecordService.save(saobeiOrderRecord);

            Map<String, Object> payParams = new HashMap<>();
            payParams.put("timeStamp", minipayResponse.getTimeStamp());
            payParams.put("nonceStr", minipayResponse.getNonceStr());
            payParams.put("package_str", minipayResponse.getPackage_str());
            payParams.put("signType", minipayResponse.getSignType());
            payParams.put("paySign", minipayResponse.getPaySign());


            Map<String, Object> result = ToolsUtils.objectToMap(payOrder);
            result.put("payParams", payParams);
            result.put("realAmount", realAmount);

            payOrder.setPayParamsStr(JSON.toJSONString(payParams));
            result.put("payParams", payParams);
            basePayOrderService.updateById(payOrder);
            return Result.OK(result);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.info("saveOrder:生成扫呗订单失败：" + minipayResponse.getReturn_msg());
            return Result.error("生成扫呗订单失败：" + minipayResponse.getReturn_msg());
        }

    }

    @AutoLog(value = "获取充值订单详情")
    @ApiOperation(value = "0510获取充值订单详情", notes = "获取充值订单详情")
    @GetMapping(value = "/porder/detail")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> payOrderDetail(@RequestParam(value = "id", required = true, defaultValue = "") String id) {
        BasePayOrder payOrder = basePayOrderService.getById(id);
        Map<String, Object> result = ToolsUtils.objectToMap(payOrder);
        result.put("payParams", JSONObject.parseObject(payOrder.getPayParamsStr()));

        return Result.ok(result);
    }

    /**
     * 充值订单支付后的逻辑处理
     * 参数：*orderId, *payType(付款方式，中文), balanceAmount(选择其他支付方式时，使用一部分会员余额), stockBalanceAmount(选择其他支付方式时，使用一部分股本余额)
     */
    @ApiOperation(value = "充值订单支付后的逻辑处理", notes = "充值订单支付后的逻辑处理")
    @PostMapping("/depositOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> depositOrder(@RequestBody Map<String, Object> map,HttpServletRequest req) {
        log.info("depositOrder, params = {}", JSON.toJSONString(map));
        String orderId = map.get("orderId") == null ? null : String.valueOf(map.get("orderId"));

        BasePayOrder payOrder = basePayOrderService.getById(orderId);
        payOrder.setPayTime(Date.from(Instant.now()));

        Double rechargeAmount = payOrder.getRechargeAmount();
        String memberId = payOrder.getMemberId();
        String stockGroupId = null;
        MemberManagement member = memberManagementService.getById(memberId);

        //记录余额变动
        if("会员余额充值".equals(payOrder.getName())&&"扫呗扫码支付".equals(payOrder.getPayType())){
            BalanceChangeRecord changeRecord = new BalanceChangeRecord();
            changeRecord.setStoreId(payOrder.getStoreId());
            changeRecord.setMemberId(payOrder.getMemberId());
            changeRecord.setMemberName(payOrder.getMemberName());
            changeRecord.setMemberPhone(payOrder.getMemberPhone());
            changeRecord.setBalanceType("M");
            changeRecord.setChangeCode("C");
            changeRecord.setOrderNo(payOrder.getOrderCode());
            changeRecord.setAmount(payOrder.getRechargeAmount());
            changeRecord.setOldValue(member.getBalance());
            changeRecord.setNewValue(changeRecord.getOldValue()+changeRecord.getAmount());
            changeRecord.setTradeTime(payOrder.getPayTime());
            balanceChangeRecordMapper.insert(changeRecord);

        }




        basePayOrderService.updateById(payOrder);
        log.warn("payorder id{} ,pay_time should not null", orderId);

        log.info("depositOrder member {}", JSON.toJSONString(member));
        Double balance = member.getBalance();
        member.setBalance(rechargeAmount + balance);

        memberManagementService.updateById(member);
        String vPayType = payOrder.getPayType();
        if (vPayType.contains("升级股东充值")){
            stockGroupId = vPayType.replace("升级股东充值", "");
            payOrder.setPayType("升级股东充值");
        }
        String storeId = payOrder.getStoreId();
        StockManage stock = null;
        if (stockGroupId!=null/*payType.equals("升级股东充值")*/) {

            log.info("升级股东充值, stockGroupId = {},storeId={},memberId={}", stockGroupId, storeId, memberId);
            List<StockManage> list = stockManageService.list(new QueryWrapper<StockManage>().eq("store_id", storeId).eq("member_id", memberId));

                log.info("listsize={}", list.size());
                if (list.size() > 0) {
                    stock = list.get(0);
                } else {
                    //以前不是股东，新建
                    StockGroup group = stockGroupService.getById(stockGroupId);
                    log.info("depositOrder group {}", JSON.toJSONString(group));
                    stock= new StockManage();
                    stock.setCardNum(Integer.valueOf(group.getCardNum()));
                    stock.setEquityTotal(Double.valueOf(group.getAmount()));
                    stock.setMemberId(memberId);
                    stock.setStockName(member.getName());
                    stock.setProrateDividends(Double.valueOf(group.getRatio()));
                    stock.setStockCard(group.getCardId());
                    stock.setStoreId(storeId);
                    stock.setShareholderDiscount(Double.valueOf(group.getDiscount()));
                    stock.setStockLowest(Double.valueOf(group.getMinAmount()));
                    stock.setTel(member.getPhone());
                    //调用pc升级股东办法
                    return stockManageController.add(stock,req);
                }
            }
            //添加记录
        //TODO  先注释掉，后面再看。。。。。。。。恶心的代码  改哭了
//            //ids 既可能是会员，也可能是股东
//            String vipId=group.getCardId();//绑定的卡号
//            AllVipcard vipcard = allVipcardService.getById(vipId);
//            if (vipcard == null) {
//                return Result.error("没有查到贵宾卡记录");
//            }
//
//            // 关联优惠劵数量
//            List<VipCardCoupon> list2 = vipCardCouponService.list(new QueryWrapper<VipCardCoupon>()
//                    .eq("store_id", storeId)
//                    .eq("vip_id", vipcard.getId()));
//
//            Integer ticketNum = list2.stream().map(VipCardCoupon::getNum).reduce(Integer::sum).orElse(0);
//            if (ticketNum == 0) {
//                return Result.error("贵宾卡还未关联优惠劵");
//            }
//            vipcard.setTicketNum(ticketNum);
//
//            if ("免费".equals(vipcard.getIsFree())) {
//                vipcard.setSellingPrice(null);
//            }
//            // 发卡记录
//            IssuingRecords issuing = new IssuingRecords();
//            issuing.setDrawTime(new Date());
//            issuing.setQuantityReceived(0);
//            issuing.setCirculation(1);
//            issuing.setToStoreNum(0);
//           // issuing.setOperator();
//            issuing.setStoreId(storeId);
//            issuing.setVipId(vipId);
//            issuing.setVipName(vipcard.getCardName());
//            issuing.setCirculation(1);
//            issuing.setCurrentAllowance(2);
//
//            // 贵宾卡关联的优惠劵，数量已从关联表中带出
//            List<CouponManagement> cmList = allVipcardMapper.listCouponsByVipId(vipId, storeId);
//
//            issuing.setStockId(stock.getId());
//            issuing.setMemberId(member.getId());
//            issuing.setMemberName(member.getName());
//            issuing.setMemberIds(member.getId());
//
//            issuingRecordsService.save(issuing);
//
//            if ("股东拓客卡".equals(vipcard.getCardType())) {
//                //StockManage sm = stockManageService.getByMemberId(memberId);
//                // 复制到会员/股东可分享贵宾卡
//                BaseMemberShareVip bmsv = new BaseMemberShareVip();
//                BeanUtils.copyProperties(vipcard, bmsv);
//                bmsv.setId(null);
//                bmsv.setCreateBy(null);
//                bmsv.setCreateTime(null);
//                bmsv.setUpdateBy(null);
//                bmsv.setUpdateTime(null);
//                bmsv.setRecordId(issuing.getId());
//                bmsv.setStockId(stock.getId());
//                bmsv.setMemberId(member.getId());
//                bmsv.setNum(1);
//                bmsv.setVedioId(vipcard.getVedioId());
//                baseMemberShareVipService.save(bmsv);
//                for (CouponManagement cm : cmList) {
//                    // 复制到会员/股东可分享贵宾卡关联的优惠劵表
//                    BaseMemberShareCoupon bmsc = new BaseMemberShareCoupon();
//                    BeanUtils.copyProperties(cm, bmsc);
//                    bmsc.setId(null);
//                    bmsc.setCreateBy(null);
//                    bmsc.setCreateTime(null);
//                    bmsc.setUpdateBy(null);
//                    bmsc.setUpdateTime(null);
//                    bmsc.setShareVipId(bmsv.getId());
//                    bmsc.setMemberId(member.getId());
//                    bmsc.setNum(Integer.parseInt(cm.getNum()));
//                    baseMemberShareCouponService.save(bmsc);
//                }
//            }
//            vipcard.setCreditNumber(vipcard.getCreditNumber() + 1);
//            allVipcardService.updateById(vipcard);
        return Result.OK();
    }

    @Resource
    private StockManageController stockManageController;


    /* <-贵宾卡样式->  */


    /**
     * 贵宾卡列表
     * 参数：*storeId
     */
    @ApiOperation(value = "贵宾卡列表", notes = "贵宾卡列表")
    @PostMapping("/listStyle")
    public Result<?> listStyle() {

        List<AllVipcardStyle> list = allVipcardStyleService.list();
        return Result.OK(list);
    }

    /**
     * 贵宾卡列表
     * 参数：*storeId
     */
    @ApiOperation(value = "贵宾卡列表", notes = "贵宾卡列表")
    @GetMapping("/getStyleDetail")
    public Result<?> getStyleDetail(@RequestParam(value = "styleId", required = true, defaultValue = "") String styleId) {
        if (isBlank(styleId)) {
            return Result.error("没有样式ID");
        }

        AllVipcardStyle style = allVipcardStyleService.getById(styleId);
        return Result.OK(style);
    }

    private Map<String, Object> getStyle(String vipId) {
        AllVipcard card = allVipcardService.getById(vipId);

        Map<String, Object> styleMap = null;
        if (card != null && card.getStyleId() != null) {
            AllVipcardStyle style = allVipcardStyleService.getById(card.getStyleId());
            if (style != null) {
                styleMap = org.jeecg.modules.util.BeanUtils.bean2Map(style);
            }
        }
        return styleMap;
    }

    private Map<String, Object> getStyle(String storeId, String cardId) {

        Map<String, Object> styleMap = null;
        List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", storeId).eq("card_id", cardId));
        if (list.size() > 0) {
            AllVipcard card = list.get(0);
            if (card != null && card.getStyleId() != null) {
                AllVipcardStyle style = allVipcardStyleService.getById(card.getStyleId());
                if (style != null) {
                    styleMap = org.jeecg.modules.util.BeanUtils.bean2Map(style);
                }
            }
        }


        return styleMap;
    }

    private Map<String, Object> getStyleById(String styleId) {


        Map<java.lang.String, java.lang.Object> styleMap = null;

        AllVipcardStyle style = allVipcardStyleService.getById(styleId);
        if (style != null) {
            styleMap = org.jeecg.modules.util.BeanUtils.bean2Map(style);
        }

        return styleMap;
    }
    /**
     *
     */
    /**
     * 商品分类列表
     * 参数：*storeId
     */
    @ApiOperation(value = "股东分组", notes = "股东分组")
    @GetMapping("/listStockGroup")
    public Result<?> listStockGroup(@RequestParam("storeId") String storeId) {


        if (StringUtils.isEmpty(storeId)) {
            return Result.error("参数不全");
        }


        List<StockGroup> list = stockGroupService.list(new QueryWrapper<StockGroup>().eq("store_id", storeId).orderByAsc("sort_no"));
        return Result.OK(list);
    }

    @AutoLog(value = "升级股东充值")
    @ApiOperation(value = "0513升级股东充值", notes = "升级股东充值")
    @PostMapping(value = "/saveStockPayOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> saveStockPayOrder(@RequestBody Map<String, Object> map) {
        String stockId = map.get("stockId") == null ? null : String.valueOf(map.get("stockId"));
        String storeId = map.get("storeId") == null ? null : String.valueOf(map.get("storeId"));
        String memberId = map.get("memberId") == null ? null : String.valueOf(map.get("memberId"));
        String saobeiType = map.get("saobeiType") == null ? null : String.valueOf(map.get("saobeiType"));
        String payName = map.get("payName") == null ? null : String.valueOf(map.get("payName"));
        String realAmount = map.get("realAmount") == null ? null : String.valueOf(map.get("realAmount"));
        String id = map.get("id") == null ? null : String.valueOf(map.get("id")); //股东分组id
        String remark = map.get("remark") == null ? "升级股东充值" : String.valueOf(map.get("remark"));
        if (StringUtils.isEmpty(storeId) || StringUtils.isEmpty(memberId) || StringUtils.isEmpty(remark) || StringUtils.isEmpty(realAmount)) {
            log.info("savePayOrder:参数不全");
            return Result.error("参数不全");
        }

        StoreInfo store = storeInfoService.getById(storeId);
        if (store == null) {
            return Result.error("没有店铺信息");
        }
        MemberManagement member = memberManagementService.getById(memberId);

        if (member == null) {
            return Result.error("没有会员信息");
        }
        BasePayOrder payOrder = new BasePayOrder();


        payOrder.setStoreId(storeId);
        payOrder.setOrderCode(ToolsUtils.getBillNo("MR"));
        payOrder.setMemberId(memberId);
        payOrder.setMemberName(member.getName());
        payOrder.setMemberPhone(member.getPhone());
        payOrder.setStockId(member.getMyStockId());
        payOrder.setRechargeAmount(Double.valueOf(realAmount));
        payOrder.setName(payName);
        payOrder.setRechargeType("升级股东充值");
        payOrder.setPayType("升级股东充值" + id);
        payOrder.setRemark("员工(" + memberId + ") 要升级到股东组(" + id + ")");


        boolean save = basePayOrderService.save(payOrder);
        if (!save) {
            Result.error("保存升级股东充值订单失败");
        }


        String xcxAppId = store.getXcxAppId();
        if (StringUtils.isEmpty(xcxAppId)) {
            log.info("saveOrder:店铺还未绑定小程序");
            return Result.error("店铺还未绑定小程序");
        }
        String saobeiMerchantNo = store.getSaobeiMerchantNo();
        String saobeiTerminalId = store.getSaobeiTerminalId();
        String saobeiAccessToken = store.getSaobeiAccessToken();
        if (StringUtils.isEmpty(saobeiMerchantNo) || StringUtils.isEmpty(saobeiTerminalId) || StringUtils.isEmpty(saobeiAccessToken)) {
            log.info("saveOrder:店铺还未绑定支付");
            return Result.error("店铺还未绑定支付");
        }

        MemberManagement mm = memberManagementService.getById(memberId);
        String xcxOpenId = mm.getXcxOpenId();
        if (StringUtils.isEmpty(xcxOpenId)) {
            log.info("saveOrder:会员还未绑定小程序");
            return Result.error("会员还未绑定小程序");
        }
        BigDecimal realAmountDecimal = new BigDecimal(realAmount);
        String totalFee = String.valueOf(realAmountDecimal.multiply(new BigDecimal("100")).intValue());

        SaobeiMiniPayResponse minipayResponse = Saobei.minipay(saobeiAccessToken, saobeiMerchantNo, saobeiTerminalId, xcxAppId, xcxOpenId, "小程序订单", payOrder.getId(), totalFee);
        if ("01".equals(minipayResponse.getResult_code())) {
            SaobeiOrderRecord saobeiOrderRecord = new SaobeiOrderRecord();
            saobeiOrderRecord.setType(saobeiType);
            saobeiOrderRecord.setOutTradeNo(minipayResponse.getOut_trade_no());
            saobeiOrderRecord.setTerminalTrace(payOrder.getId());
            saobeiOrderRecord.setTotalFee(totalFee);
            saobeiOrderRecord.setStoreId(storeId);
            saobeiOrderRecord.setCreateBy("xcx");
            saobeiOrderRecordService.save(saobeiOrderRecord);

            Map<String, Object> payParams = new HashMap<>();
            payParams.put("timeStamp", minipayResponse.getTimeStamp());
            payParams.put("nonceStr", minipayResponse.getNonceStr());
            payParams.put("package_str", minipayResponse.getPackage_str());
            payParams.put("signType", minipayResponse.getSignType());
            payParams.put("paySign", minipayResponse.getPaySign());


            Map<String, Object> result = ToolsUtils.objectToMap(payOrder);
            result.put("payParams", payParams);
            result.put("realAmount", realAmount);

            payOrder.setPayParamsStr(JSON.toJSONString(payParams));
            result.put("payParams", payParams);
            basePayOrderService.updateById(payOrder);
            return Result.OK(result);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.info("saveOrder:生成扫呗订单失败：" + minipayResponse.getReturn_msg());
            return Result.error("生成扫呗订单失败：" + minipayResponse.getReturn_msg());
        }


    }

    @AutoLog(value = "获取股东升级支付详情")
    @ApiOperation(value = "0512获取股东升级支付详情", notes = "获取股东升级支付详情")
    @GetMapping(value = "/stockorder/detail")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> stockPayOrderDetail(@RequestParam(value = "id", required = true, defaultValue = "") String id) {
        BasePayOrder payOrder = basePayOrderService.getById(id);
        Map<String, Object> result = ToolsUtils.objectToMap(payOrder);
        result.put("payParams", JSONObject.parseObject(payOrder.getPayParamsStr()));

        return Result.ok(result);
    }

    public String getVipId(String storeId, Integer cardId) {
        List<AllVipcard> list = allVipcardService.list(new QueryWrapper<AllVipcard>().eq("store_id", storeId).eq("card_id", cardId));
        if (list.size() == 1) {
            return list.get(0).getId();
        }
        return "";
    }


    private void giveHighStock(String storeId, String stockId, BigDecimal realAmountDecimal) {
        List<String> highStocks = getHighStock(storeId, stockId);
        if (highStocks.size() > 0) {
            String s = highStocks.get(0);
            StockManage stock = stockManageService.getById(s);
            String shareholdersHousekeeperId = stock.getShareholdersHousekeeperId();

            if (StringUtils.isBlank(shareholdersHousekeeperId) && staffManagementService.getById(shareholdersHousekeeperId) != null) {
                StaffManagement dividendStaff = staffManagementService.getById(shareholdersHousekeeperId);
                BigDecimal ratio = new BigDecimal(String.valueOf(stock.getShareholdersRatio()));
                BigDecimal staffShareMoney = realAmountDecimal.multiply(ratio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                // 分红
                BigDecimal totalShare = new BigDecimal(String.valueOf(dividendStaff.getTotalShare()));
                dividendStaff.setTotalShare(totalShare.add(staffShareMoney).doubleValue());
                // 总薪资
                BigDecimal totalSalary = new BigDecimal(String.valueOf(dividendStaff.getTotalSalary()));
                dividendStaff.setTotalSalary(totalSalary.add(staffShareMoney).doubleValue());
                staffManagementService.updateById(dividendStaff);


                Double indirectProrateDividends = stock.getIndirectProrateDividends();
                if (indirectProrateDividends == null) {
                    indirectProrateDividends = 0.0;
                }
                BigDecimal inBigDecimal = new BigDecimal(indirectProrateDividends);
                BigDecimal subtract = realAmountDecimal.subtract(staffShareMoney);
                indirectProrateDividends = inBigDecimal.add(subtract).doubleValue();
                stock.setIndirectDividend(indirectProrateDividends);
                stockManageService.updateById(stock);

            } else {
                Double indirectProrateDividends = stock.getIndirectProrateDividends();
                if (indirectProrateDividends == null) {
                    indirectProrateDividends = 0.0;
                }
                BigDecimal inBigDecimal = new BigDecimal(indirectProrateDividends);

                indirectProrateDividends = inBigDecimal.add(realAmountDecimal).doubleValue();
                stock.setIndirectDividend(indirectProrateDividends);
                stockManageService.updateById(stock);

            }

        }

    }

    private void giveStaffMoney(String storeId, String staffId, String type, BigDecimal realAmountDecimal) {
        StaffManagement staff = staffManagementService.getById(staffId);
        if (staff == null) {
            log.warn("staff[id{}] is null ", staffId);
            return;
        }
        if ("1".equals(type)) {
            Double sellMoney = staff.getSellMoney();
            if (sellMoney == null) {
                sellMoney = 0.0;
            }
            sellMoney = plus(sellMoney, realAmountDecimal);
            staff.setSellMoney(sellMoney);
        } else {
            Double serveMoney = staff.getServeMoney();
            if (serveMoney == null) {
                serveMoney = 0.0;
            }
            serveMoney = plus(serveMoney, realAmountDecimal);
            staff.setSellMoney(serveMoney);
        }

        staffManagementService.updateById(staff);
    }

    private Double plus(Double money, BigDecimal realAmountDecimal) {
        return money.doubleValue() + realAmountDecimal.doubleValue();
    }
}